【问题标题】:WPF/Silverlight: How to bind ItemsControl based UI element to an ItemsControl property on the ViewModel?WPF/Silverlight:如何将基于 ItemsControl 的 UI 元素绑定到 ViewModel 上的 ItemsControl 属性?
【发布时间】:2010-12-22 23:00:19
【问题描述】:

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

在我的视图中,我有 2 个列表框,它们派生自 ItemsControl。 在我的视图模型上,我想公开 2 个 ItemsControl 属性,这样我就可以将我的列表框绑定到这个视图模型属性......这样我就可以从视图模型中实现一个命令,让我从ListBox1 到 ListBox2。

想象一下以下 sn-ps 中没有显示的所有非常酷的东西:

查看模型代码:

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

谢谢!

【问题讨论】:

    标签: c# wpf mvvm binding itemscontrol


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您不应该在视图模型中实现控件。这使它成为一个视图,而不是一个视图的模型。您的视图模型上的属性应该是ObservableCollection&lt;T&gt;,并且您应该将项目控件的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>
      

      List1List2ObservableCollection&lt;T&gt; 类型,SelectedItem1SelectedItem2T 类型(无论你决定 T 应该是什么类型),MoveItemFromList1ToList2CommandRoutedCommand 定义了这两个处理程序:

      public bool CanMoveItemFromList1ToList2
      {
         { get { return SelectedItem1 != null; }
      }
      
      public void MoveItemFromList1ToList2()
      {
         List2.Add(SelectedItem1);
         List1.Remove(SelectedItem1);
      }
      

      我必须测试这段代码才能确定,但​​我认为您不需要为MoveItemFromList1ToList2 方法中的属性更改通知而烦恼;当您从 List1 中删除项目时,ObservableCollection 将通知 ListBox 该项目已被删除,ListBox 将设置 SelectedItem 为 null,更新视图模型中的 SelectedItem1。 (当然,如果在将其添加到第二个集合之前将其从第一个集合中删除,这将导致代码中断。)

      【讨论】:

      • 感谢 Rob/devdigital 的回复。我已经拥有用作 ItemSource 的 ObservableCollection 属性和视图模型上的属性。
        我想我的问题是,如果我没有对 UI 控件的引用,如何将项目从一个列表框移动到另一个列表框。
      • 你没有。您将它从一个集合移动到另一个集合,数据绑定会为您更新列表框。
      • 谢谢,我现在明白了。比我的黑客攻击要容易得多。
      猜你喜欢
      • 1970-01-01
      • 2011-06-29
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 1970-01-01
      相关资源
      最近更新 更多