WPF / Silverlight: Как связать элемент пользовательского интерфейса ItemsControl со свойством ItemsControl в ViewModel? - PullRequest
0 голосов
/ 23 декабря 2010

Будучи новичком в WPF / XAML / MVVM, у меня есть вопрос.

В моем представлении у меня есть 2 списка, которые являются производными от ItemsControl. На моей модели представления я хотел бы предоставить 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}...../>

учитывая, что я хочу, чтобы моя модель представления могла иметь команду, которая могла бы перемещать элементы из одного списка в другой, с кодом, таким как:

public void MoveItemCommandExecute(...)
{
   var sourceItem = MyStuff1ItemsControl.MagicGetItemExtensionMehod(MyStuff1SelectedIndex);
   MyStuff1ItemsControl.MagicRemoveItemExtensionMethod(MyStuff1SelectedIndex);

   MyStuff2ItemsControl.MagicAddItemExtensionMethod(sourceItem);
}

так, в принципе, как будет выглядеть обязательный XAML? Я пытаюсь установить свойство для модели представления из представления ...

спасибо!

Ответы [ 2 ]

1 голос
/ 23 декабря 2010

Вы захотите переосмыслить этот подход.Как правило, вы привязываете два свойства ItemsSource вашего списка к двум ObservableCollection<T> свойствам в вашей модели представления, где T - это тип объекта в вашем списке.

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

Примечание: я бы использовал x: Name вваш XAML, а не атрибут 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 или определяя шаблон элемента в каждом списке.

Вы можете поменять местами элементы междусписки с использованием стандартных методов Collection для типа ObservableCollection - http://msdn.microsoft.com/en-us/library/ms668604.aspx

0 голосов
/ 23 декабря 2010

Вы не должны реализовывать элементы управления в вашей модели представления. Это делает его представлением, а не моделью представления. Свойства вашей модели представления должны быть 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 (каким бы типом вы ни выбрали 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 в ноль, обновив SelectedItem1 в модели представления. (И, конечно, это приведет к разрыву кода, если вы удалите его из первой коллекции перед добавлением во вторую.)

...