【问题标题】:Multiple ItemsSource collection bindings多个 ItemsSource 集合绑定
【发布时间】:2011-03-26 22:33:47
【问题描述】:

如何将多个不同类型的集合绑定到 ItemsControl 的 ItemsSource?

使用单个绑定可以正常工作:

<ItemsControl ItemsSource="{Binding Foo}" />

但是当我尝试使用 CompositeCollection 时,Foo 中的项目不会显示:

    <ItemsControl>
        <ItemsControl.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding Foo}" />
            </CompositeCollection>
        </ItemsControl.ItemsSource>
    </ItemsControl>

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    我建议将 ListBox 绑定到您在代码中构建的 CompositeCollection。 在此示例中,我使用的是 ViewModel,但您也可以在代码隐藏中执行相同操作。 您可以通过 google 找到很多关于如何为 ViewModel 实现 ViewModelBase 和 DelegateCommand 的示例。

    下面是这个例子的细目:

    • 此示例将 Customer 和 Person 对象加载到两个 ObservableCollection 容器中以支持修改集合。
    • ListBox 将其 ItemsSource 绑定到包含两个 ObservableCollection 的 CompositeCollection (ObjectCollection)。
    • ListBox 还将其 SelectedItem 绑定到一个对象 (SelectedObject) 以支持两种基本类型。
    • Button 添加了一个新 Person 以显示您可以修改 CompositeCollection。
    • 为了完整起见,我在末尾添加了客户和人员定义。

    这里是视图:

    <Window x:Class="StackOverflow.Views.MainView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Main Window" Height="400" Width="800">
      <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListBox Grid.Row="0" 
                 SelectedItem="{Binding Path=SelectedObject}"
                 ItemsSource="{Binding Path=ObjectCollection}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Label Content="{Binding FirstName}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Grid.Row="1" Content="Add Person" Command="{Binding Path=AddPerson}"/>
      </Grid>
    </Window>
    

    这是视图模型:

    using System.Collections.Generic;
    using System.Windows.Data;
    using System.Windows.Input;
    using ContextMenuNotFiring.Commands;
    using ContextMenuNotFiring.Models;
    
    namespace StackOverflow.ViewModels
    {
      public class MainViewModel : ViewModelBase
      {
        public MainViewModel()
        {
          AddPerson = new DelegateCommand<object>(OnAddPerson, CanAddPerson);
    
          CollectionContainer customers = new CollectionContainer();
          customers.Collection = Customer.GetSampleCustomerList();
    
          CollectionContainer persons = new CollectionContainer();
          persons.Collection = Person.GetSamplePersonList();
    
          _oc.Add(customers);
          _oc.Add(persons);
        }
    
        private CompositeCollection _oc = new CompositeCollection();
        public CompositeCollection ObjectCollection
        {
          get { return _oc; }
        }
    
        private object _so = null;
        public object SelectedObject
        {
          get { return _so; }
          set
          {
           _so = value;
          }
        }
    
        public ICommand AddPerson { get; set; }
        private void OnAddPerson(object obj)
        {
          CollectionContainer ccItems = _oc[1] as CollectionContainer;
          if ( ccItems != null )
          {
            ObservableCollection<Person> items = ccItems.Collection as ObservableCollection<Person>;
            if (items != null)
            {
              Person p = new Person("AAAA", "BBBB");
              items.Add(p);
            }
          }
        }
    
        private bool CanAddPerson(object obj)
        {
          return true;
        }
      }
    }
    

    以下是模型:

    public class Customer
    {
      public String FirstName { get; set; }
      public String LastName { get; set; }
    
      public Customer(String firstName, String lastName)
      {
         this.FirstName = firstName;
         this.LastName = lastName;
      }
    
      public static ObservableCollection<Customer> GetSampleCustomerList()
      {
        return new ObservableCollection<Customer>(new Customer[4] {
                new Customer("Charlie", "Zero"), 
                new Customer("Cathrine", "One"),
                new Customer("Candy", "Two"),
                new Customer("Cammy", "Three")
            });
      }
    }
    
    
    public class Person
    {
      public String FirstName { get; set; }
      public String LastName { get; set; }
    
      public Person(String firstName, String lastName)
      {
         this.FirstName = firstName;
         this.LastName = lastName;
      }
    
      public static ObservableCollection<Person> GetSamplePersonList()
      {
        return new ObservableCollection<Person>(new Person[4] {
                new Person("Bob", "Smith"), 
                new Person("Barry", "Jones"),
                new Person("Belinda", "Red"),
                new Person("Benny", "Hope")
            });
      }
    }
    

    【讨论】:

    • 在代码后面/VM 中构建 CompositeCollection 而不是在 XAML 中使用 CollectionContainer 绑定到 VM 的相应属性有什么优势?
    【解决方案2】:

    我相信这里得到了最好的回答:How do you bind a CollectionContainer to a collection in a view model?

    归结为CollectionContainer 没有DataContext。您必须设置源,以便它可以找到DataContext 并完成绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-10
      • 2012-12-10
      • 1970-01-01
      • 2015-09-08
      • 2015-02-05
      • 2013-04-11
      • 1970-01-01
      • 2018-07-16
      相关资源
      最近更新 更多