我在没有MVVM的WPF中有一个应用程序,我决定将其重构为MVVM。我遇到了ComboBox SelectionChanged事件的问题。基本上让它变得更简单,假设我有一个ComboBox和2个ListView。每个ComboBoxItem都是一个集合。第一个ListView的ItemsSource绑定到ComboBox.SelectedValue的集合,但仅限于其一个属性(十进制)大于零的部分。第二个ListView的ItemsSource绑定到相同的集合,但绑定到第二个部分(一些prop大于零)。下面是一些代码来理解
private void myCombo_selectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox myCmb = sender as ComboBox;
List<myType> myList = myCmb.SelectedValue as List<myType>;
itemsForListView1 = myList.Where((x) => x.myProp > 0);
itemsForListView2 = myList.Where((x) => x.myProp < 0);
// Above 2 collections are of Type List<myType> and their scope will be whole ViewModel,
//so i assume i just need to change them and RaisePropChanged but how to change them without breaking mvvm ?
MyListView1.ItemsSource = itemsForListView1;
MyListView2.ItemsSource = itemsForListView2;
}
如何在MVVM中实现类似的东西?
答案 0 :(得分:2)
我建议使用下面的伪代码解决方案。将SelectedItem与myCombo的SelectedValue和ItemsListViewX与ListView绑定
private List<T> selectedItem;
public List<T> SelectedItem
{
get { return selectedItem; }
set
{
if (value != selectedItem)
{
selectedItem = value;
ItemsListView1 = new ObservableCollection<T>(selectedItem.Where(x=>x.Prop>0));
ItemsListView2 = new ObservableCollection<T>(selectedItem.Where(x=>x.Prop<0));
NotifyOfPropertyChange(() => SelectedItem);
}
}
}
private ObservableCollection<T> itemsListView1;
public ObservableCollection<T> ItemsListView1
{
get { return itemsListView1; }
set
{
if (value != itemsListView1)
{
itemsListView1 = value;
NotifyOfPropertyChange(() => ItemsListView1);
}
}
}
private ObservableCollection<T> itemsListView2;
public ObservableCollection<T> ItemsListView2
{
get { return itemsListView2; }
set
{
if (value != itemsListView2)
{
itemsListView2 = value;
NotifyOfPropertyChange(() => ItemsListView2);
}
}
}
也许您对MVVM Framework感兴趣。它会增强你的数据绑定。
答案 1 :(得分:1)
如果我理解正确您想要的是处理ViewModel中的SelectionChanged
并对itemsForListView1
和itemsForListView2
进行一些更改,而不是对您目前在View中执行的操作进行更改?
1)在ViewModel中,您需要:创建一个ICommand
公共属性,可以从DelegateCommand
实例化为Microsoft.Practices.Composite.Presentation.Commands
:
...
public ViewModelConstructor(...)
{
...
SelectionChangedCommand = new DelegateCommand<List<myType>>(SelectionChangedExecute);
...
}
...
public List<myType> ItemsForListView1 {get; private set} // Implement INotifyPropertyChanged here
public List<myType> ItemsForListView1 {get; private set} // Implement INotifyPropertyChanged here
...
public ICommand SelectionChangedCommand { get; private set; }
private void SelectionChangedExecute(List<myType> parameter)
{
ItemsForListView1 = parameter.Where((x) => x.myProp > 0).ToList();
ItemsForListView2 = parameter.Where((x) => x.myProp < 0).ToList();
}
...
2)在视图中,您希望将Loaded和SelectionChanged绑定到viewmodel中新创建的命令,并且您希望ListView绑定到ViewModel中的集合
<ComboBox x:Name="MyComboBox" SelectedIndex="0" ItemsSource="{Binding YourCollectionWithDifferentLists}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=Combo, Path=SelectedItem}"></i:InvokeCommandAction>
</i:EventTrigger>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=Combo, Path=SelectedItem}"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
如果您的集合正在更改并且您想要在UI上显示更改,则可能需要使用ObservableCollection而不是List。如果要在选择更改事件后创建新集合,则需要以任一方式实现INotifyPropertyChanged。