WPF MVVM иерархия выбранного элемента - PullRequest
4 голосов
/ 22 марта 2012

Я в настоящее время реализую приложение, которое отображает иерархию с использованием ListBoxes (не рекомендуется использовать TreeView, ListBoxes необходимо).

Похоже, что в статье: WPF CollectionViewSource (с исходным кодом) .

enter image description here

Классы:

public class Mountains : ObservableCollection<Mountain>
{
    public ObservableCollection<Lift> Lifts { get; }

    public string Name { get; }
}

public class Lift
{
    public ObservableCollection<string> Runs { get; }
}

В примере используются CollectionViewSource экземпляры(см. XAML) для упрощения дизайна.Экземпляр класса Mountains является DataContext для окна.


Проблема заключается в следующем: я хотел бы, чтобы класс Mountains имел свойство SelectedRun, и его следует установить втекущий выбранный прогон.

public class Mountains : ObservableCollection<Mountain>
{
    public ObservableCollection<Lift> Lifts { get; }

    public string Name { get; }

    public string SelectedRun { get; set; }
}

Может быть, я пропустил какой-то базовый принцип, но как мне этого добиться?

Ответы [ 3 ]

4 голосов
/ 23 марта 2012

Возможно, вы захотите прочитать об использовании «/» в привязках. См. Раздел «Указатели текущего элемента» в этой статье MSDN .

Вот мое решение:

Xaml

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <TextBlock Margin="5" Grid.Row="0" Grid.Column="0" Text="Mountains"/>
    <TextBlock Margin="5" Grid.Row="0" Grid.Column="1" Text="Lifts"/>
    <TextBlock Margin="5" Grid.Row="0" Grid.Column="2" Text="Runs"/>

    <ListBox Grid.Row="1" Grid.Column="0" Margin="5" 
             ItemsSource="{Binding Mountains}" DisplayMemberPath="Name" 
             IsSynchronizedWithCurrentItem="True" />

    <ListBox Grid.Row="1" Grid.Column="1" Margin="5" 
             ItemsSource="{Binding Mountains/Lifts}" DisplayMemberPath="Name" 
             IsSynchronizedWithCurrentItem="True"/>

    <ListBox Grid.Row="1" Grid.Column="2" Margin="5" 
             ItemsSource="{Binding Mountains/Lifts/Runs}" 
             IsSynchronizedWithCurrentItem="True" 
             SelectedItem="{Binding SelectedRun}"/>
</Grid>

C # (обратите внимание, вам не нужно реализовывать INotifyPropertyChanged, если только свойства не будут изменены, а не просто выбраны)

public class MountainsViewModel
{
    public MountainsViewModel()
    {
        Mountains = new ObservableCollection<Mountain>
                        {
                            new Mountain
                                {
                                    Name = "Whistler",
                                    Lifts = new ObservableCollection<Lift>
                                                {
                                                    new Lift
                                                        {
                                                            Name = "Big Red",
                                                            Runs = new ObservableCollection<string>
                                                                       {
                                                                           "Headwall",
                                                                           "Fisheye",
                                                                           "Jimmy's"
                                                                       }
                                                        },
                                                    new Lift
                                                        {
                                                            Name = "Garbanzo",
                                                            Runs = new ObservableCollection<string>
                                                                       {
                                                                           "Headwall1",
                                                                           "Fisheye1",
                                                                           "Jimmy's1"
                                                                       }
                                                        },
                                                    new Lift {Name = "Orange"},
                                                }

                                },
                            new Mountain
                                {
                                    Name = "Stevens",
                                    Lifts = new ObservableCollection<Lift>
                                                {
                                                    new Lift {Name = "One"},
                                                    new Lift {Name = "Two"},
                                                    new Lift {Name = "Three"},
                                                }

                                },
                            new Mountain {Name = "Crystal"},
                        };
    }

    public string Name { get; set; }
    private string _selectedRun;
    public string SelectedRun
    {
        get { return _selectedRun; }
        set
        {
            Debug.WriteLine(value);
            _selectedRun = value;
        }
    }

    public ObservableCollection<Mountain> Mountains { get; set; }
}

public class Mountain
{
    public string Name { get; set; }

    public ObservableCollection<Lift> Lifts { get; set; }
}

public class Lift
{
    public string Name { get; set; }

    public ObservableCollection<string> Runs { get; set; }
}
2 голосов
/ 22 марта 2012

Вот как бы я это сделал.Вы хотите убедиться, что вы запускаете событие INotifyPropertyChanged при установке свойств.Чтобы получить выбранный прогон, вам нужно получить MainViewModel.SelectedMountain.SelectedLift.SelectedRun.

public class MainViewModel: ViewModelBae
{
    ObservableCollection<MountainViewModel> mountains
    public ObservableCollection<MountainViewModel> Mountains
    {
        get { return mountains; }
        set
        {
            if (mountains != value)
            {
                mountains = value;
                RaisePropertyChanged("Mountains");
            }
        }
    }
    MountainViewModel selectedMountain
    public MountainViewModel SelectedMountain
    {
        get { return selectedMountain; }
        set
        {
            if (selectedMountain != value)
            {
                selectedMountain = value;
                RaisePropertyChanged("SelectedMountain");
            }
        }
    }
}

public class MountainViewModel: ViewModelBae
{
    ObservableCollection<LiftViewModel> lifts
    public ObservableCollection<LiftViewModel> Lifts
    {
        get { return lifts; }
        set
        {
            if (lifts != value)
            {
                lifts = value;
                RaisePropertyChanged("Lifts");
            }
        }
    }
    LiftViewModel selectedLift
    public LiftViewModel SelectedLift
    {
        get { return selectedLift; }
        set
        {
            if (selectedLift != value)
            {
                selectedLift = value;
                RaisePropertyChanged("SelectedLift");
            }
        }
    }
}

public class LiftViewModel: ViewModelBae
{
    ObservableCollection<string> runs
    public ObservableCollection<string> Runs
    {
        get { return runs; }
        set
        {
            if (runs != value)
            {
                runs = value;
                RaisePropertyChanged("Runs");
            }
        }
    }
    string selectedRun
    public string SelectedRun
    {
        get { return selectedLift; }
        set
        {
            if (selectedLift != value)
            {
                selectedLift = value;
                RaisePropertyChanged("SelectedLift");
            }
        }
    }
}

<ListBox ItemsSource="{Binding Mountains}" SelectedItem="{Binding SelectedMountain, Mode=TwoWay}">
<ListBox ItemsSource="{Binding SelectedMountain.Lifts}" SelectedItem="{Binding SelectedMountain.SelectedLift, Mode=TwoWay}">
<ListBox ItemsSource="{Binding SelectedMountain.SelectedLift.Runs}" SelectedItem="{Binding SelectedMountain.SelectedLift.SelectedRun, Mode=TwoWay}">
0 голосов
/ 22 марта 2012

Ваша ViewModel также не должна быть коллекцией, она должна содержать коллекции и свойства, которые привязаны к представлению. SelectedRun должен быть свойством этой ViewModel (MountainViewModel), а не Mountains. MountainViewModel должен предоставлять коллекцию Mountains и SelectedRun и должен быть привязан к спискам ItemsSource и SelectedItem.

...