开发者

WPF/Silverlight: How to bind ItemsControl based UI element to an ItemsControl property on the ViewModel?

Being a new to WPF/XAML/MVVM, I've got a question.

In my View, I have 2 listboxes, which derive from ItemsControl. On my viewmodel, I'd like to expose 2 ItemsControl properties such that I can bind my listbox to this view model property... this way I can implement a command that, from the view model, lets me move the currently selected item from ListBox1 to ListBox2.

Imagine all the really cool stuff not shown the following snippets:

view model code:

public int MyStuff1SelectedIndex { get{...} set{...} }
public int MyStuff2SelectedIndex { get{...} set{...} }
public ItemsControl MyStuffItemsControl1 { set; private get; }
public ItemsControl MyStuffItemsControl2 { set; private set; }

view XAML:

   <ListBox Name="x:MyStuffListBox1" SelectedIndex="{Binding MyStuff1SelectedIndex}.... />
   <ListBox Name="x:MyStuffListBox2" SelectedIndex="{Binding MyStuff2SelectedIndex}...../>

given that, I want my viewmodel to be able to have a command which could move items from one list box to another, w/ code such as the following:

public void MoveItemCommandExecute(...)
{
   var sourceItem = MyStuff1ItemsControl.MagicGetItemExtensionMehod(MyStuff1SelectedIndex);
   MyStuff1ItemsControl.MagicRemoveItemExtensionMethod(MyStuff开发者_运维技巧1SelectedIndex);

   MyStuff2ItemsControl.MagicAddItemExtensionMethod(sourceItem);
}

so, basically, what would the binding XAML look like ? I am trying to set a property on the view model from the view...

thanks!


You'll want to rethink this approach. Typically, you would bind your two listboxes ItemsSource properties to two ObservableCollection<T> properties on your view model, where T is the type of object in your list.

<ListBox x:Name="MyStuffListBox1" ItemsSource="{Binding MyList1}" SelectedItem="{Binding SelectedList1Item}" />
<ListBox x:Name="MyStuffListBox2" ItemsSource="{Binding MyList2}" SelectedItem="{Binding SelectedList2Item}" />

Note: I would use x:Name in your XAML, rather than the Name attribute.

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());
} 

You can then format what is displayed in the lists using DisplayMemberPath or defining an ItemTemplate on each list.

You can swap items between the lists by using the standard Collection methods on the ObservableCollection type - http://msdn.microsoft.com/en-us/library/ms668604.aspx


You shouldn't be implementing controls in your view model. That makes it a view, not a model of a view. The properties on your view model should be ObservableCollection<T>, and you should be binding the ItemsSource of items controls to those properties.

If you do this, your XAML might look like this:

<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 and List2 are of type ObservableCollection<T>, SelectedItem1 and SelectedItem2 are of type T (whatever type you've decided T should be), and MoveItemFromList1ToList2Command is a RoutedCommand that has these two handlers defined:

public bool CanMoveItemFromList1ToList2
{
   { get { return SelectedItem1 != null; }
}

public void MoveItemFromList1ToList2()
{
   List2.Add(SelectedItem1);
   List1.Remove(SelectedItem1);
}

I'd have to test this code to be sure, but I don't think you need to bother with property-change notification in the MoveItemFromList1ToList2 method; when you remove the item from List1, the ObservableCollection will notify the ListBox that the item's been removed, and the ListBox will set SelectedItem to null, updating SelectedItem1 in the view model. (And, of course, that will make the code break if you remove it from the first collection before adding it to the second.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜