I am currently implementing the application that displays hierarchy using ListBoxes
(please do not suggest using TreeView
, ListBoxes
are needed).
It looks like that in the article: WPF’s CollectionViewSource (with source code).
Classes:
public class Mountains : ObservableCollection<Mountain>
{
public ObservableCollection<Lift> Lifts { get; }
public string Name { get; }
}
public class Lift
{
public ObservableCollection<string> Runs { get; }
}
The example uses CollectionViewSource
instances (see XAML) to simplify the design.
An instance of Mountains
class is the DataContext
for the window.
The problem is: I would like that the Mountains
class to have SelectedRun
property and it should be set to currently selected run.
public class Mountains : ObservableCollection<Mountain>
{
public ObservableCollection<Lift> Lifts { get; }
public string Name { get; }
public string SelectedRun { get; set; }
}
Maybe I've missed something basic principle, but how can I achieve this?
You may want to read about the use of '/' in bindings. See the section 'current item pointers' on this MSDN article.
Here's my solution:
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# (note, you don't need to implement INotifyPropertyChanged unless the properties will be changed and not just selected)
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; }
}