WPF / Silverlight:如何将基于ItemsControl的UI元素绑定到ViewModel上的ItemsControl属性?

时间:2010-12-22 23:00:19

标签: c# wpf mvvm binding itemscontrol

作为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会是什么样子?我试图从视图中设置视图模型的属性...

谢谢!

2 个答案:

答案 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>

List1List2类型为ObservableCollection<T>SelectedItem1SelectedItem2属于T类型(您决定使用的任何类型{ {1}}应该是),TMoveItemFromList1ToList2Command,它定义了这两个处理程序:

RoutedCommand

我必须测试此代码才能确定,但​​我认为您不需要在public bool CanMoveItemFromList1ToList2 { { get { return SelectedItem1 != null; } } public void MoveItemFromList1ToList2() { List2.Add(SelectedItem1); List1.Remove(SelectedItem1); } 方法中使用属性更改通知。当您从MoveItemFromList1ToList2移除该项目时,List1会通知ObservableCollection该项目已被删除,而ListBox会将ListBox设置为空,更新视图模型中的SelectedItem。 (当然,如果在将其添加到第二个集合之前将其从第一个集合中删除,这将使代码中断。)