作为WPF / XAML / MVVM的新手,我有一个问题。
在我的视图中,我有2个列表框,它们派生自ItemsControl。 在我的viewmodel上,我想公开2个ItemsControl属性,这样我就可以将我的列表框绑定到这个视图模型属性......这样我就可以实现一个命令,从视图模型中,我可以移动当前选中的项目ListBox1到ListBox2。
想象一下所有非常酷的东西都没有显示以下片段:
查看型号代码:
public int MyStuff1SelectedIndex { get{...} set{...} }
public int MyStuff2SelectedIndex { get{...} set{...} }
public ItemsControl MyStuffItemsControl1 { set; private get; }
public ItemsControl MyStuffItemsControl2 { set; private set; }
查看XAML:
<ListBox Name="x:MyStuffListBox1" SelectedIndex="{Binding MyStuff1SelectedIndex}.... />
<ListBox Name="x:MyStuffListBox2" SelectedIndex="{Binding MyStuff2SelectedIndex}...../>
鉴于此,我希望我的viewmodel能够拥有一个命令,可以将项目从一个列表框移动到另一个列表框,具有如下代码:
public void MoveItemCommandExecute(...)
{
var sourceItem = MyStuff1ItemsControl.MagicGetItemExtensionMehod(MyStuff1SelectedIndex);
MyStuff1ItemsControl.MagicRemoveItemExtensionMethod(MyStuff1SelectedIndex);
MyStuff2ItemsControl.MagicAddItemExtensionMethod(sourceItem);
}
所以,基本上,绑定XAML会是什么样子?我试图从视图中设置视图模型的属性...
谢谢!
答案 0 :(得分:1)
您需要重新考虑这种方法。通常,您可以将两个列表框ItemsSource属性绑定到视图模型上的两个ObservableCollection<T>
属性,其中T是列表中对象的类型。
<ListBox x:Name="MyStuffListBox1" ItemsSource="{Binding MyList1}" SelectedItem="{Binding SelectedList1Item}" />
<ListBox x:Name="MyStuffListBox2" ItemsSource="{Binding MyList2}" SelectedItem="{Binding SelectedList2Item}" />
注意:我会在XAML中使用x:Name,而不是Name属性。
public ObservableCollection<Thing> MyList1 { get; set; }
public ObservableCollection<Thing> MyList2 { get; set; }
// these properties should raise property changed events (INotifyPropertyChanged)
public Thing SelectedList1Item { get {...} set {...} }
public Thing SelectedList2Item { get {...} set {...} }
// constructor
public MyViewModel()
{
// instantiate and populate lists
this.MyList1 = new ObservableCollection(this.service.GetThings());
this.MyList2 = new ObservableCollection(this.service.GetThings());
}
然后,您可以使用DisplayMemberPath格式化列表中显示的内容,或在每个列表上定义ItemTemplate。
您可以使用ObservableCollection类型上的标准Collection方法在列表之间交换项目 - http://msdn.microsoft.com/en-us/library/ms668604.aspx
答案 1 :(得分:0)
您不应该在视图模型中实现控件。这使它成为一个视图,而不是视图的模型。视图模型上的属性应为ObservableCollection<T>
,您应该将ItemsSource
项控件绑定到这些属性。
如果您这样做,您的XAML可能如下所示:
<ListBox ItemsSource="{Binding List1}" SelectedItem="{Binding SelectedItem1, Mode=TwoWay}"/>
<ListBox ItemsSource="{Binding List2}" SelectedItem="{Binding SelectedItem2, Mode=TwoWay}"/>
<Button Command="{Binding MoveItemFromList1ToList2Command}">Move</Button>
List1
和List2
类型为ObservableCollection<T>
,SelectedItem1
和SelectedItem2
属于T
类型(您决定使用的任何类型{ {1}}应该是),T
是MoveItemFromList1ToList2Command
,它定义了这两个处理程序:
RoutedCommand
我必须测试此代码才能确定,但我认为您不需要在public bool CanMoveItemFromList1ToList2
{
{ get { return SelectedItem1 != null; }
}
public void MoveItemFromList1ToList2()
{
List2.Add(SelectedItem1);
List1.Remove(SelectedItem1);
}
方法中使用属性更改通知。当您从MoveItemFromList1ToList2
移除该项目时,List1
会通知ObservableCollection
该项目已被删除,而ListBox
会将ListBox
设置为空,更新视图模型中的SelectedItem
。 (当然,如果在将其添加到第二个集合之前将其从第一个集合中删除,这将使代码中断。)