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

发布于 2024-10-09 00:45:19 字数 1157 浏览 5 评论 0原文

作为 WPF/XAML/MVVM 的新手,我有一个问题。

在我的视图中,我有 2 个列表框,它们派生自 ItemsControl。 在我的视图模型上,我想公开 2 个 ItemsControl 属性,以便我可以将列表框绑定到此视图模型属性...这样我可以实现一个命令,从视图模型中,我可以将当​​前选定的项目从列表框 1 到列表框 2。

想象一下所有非常酷的东西都没有显示以下片段:

查看模型代码:

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

谢谢!

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

   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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美胚控场 2024-10-16 00:45:19

您需要重新考虑这种方法。通常,您会将两个列表框 ItemsSource 属性绑定到视图模型上的两个 ObservableCollection 属性,其中 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

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

一瞬间的火花 2024-10-16 00:45:19

您不应该在视图模型中实现控件。这使它成为一个视图,而不是视图的模型。视图模型上的属性应该是 ObservableCollection,并且您应该将项目控件的 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 的类型为 ObservableCollectionSelectedItem1 和 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 设置为 null,从而更新视图模型中的 SelectedItem1。 (当然,如果您在将其添加到第二个集合之前将其从第一个集合中删除,这将使代码中断。)

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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文