WPF MVVM层次结构选择项 [英] WPF MVVM hierarchy selected item
问题描述
我当前正在使用ListBoxes
实现显示层次结构的应用程序(请不要建议使用TreeView
,需要使用ListBoxes
).
在以下文章中看起来像> WPF的CollectionViewSource(带有源代码).
课程:
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; }
}
也许我错过了一些基本原理,但是我该如何实现呢?
您可能想阅读有关在绑定中使用'/'的信息.请参见此 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; }
}
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; }
}
这篇关于WPF MVVM层次结构选择项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!