将不同的集合绑定到datagrid

时间:2013-09-30 07:33:48

标签: c# wpf data-binding datagrid observablecollection

我有一些收藏品。例如,List 1List 2。两者都是List<Object>

我需要做什么:

1)将它们插入Datagrid

Datagrid with lists

2)为Lists添加新项目。例如,表单上有一些按钮。我点击它,新项目正在添加到第一个列表。 Datagrid现在看起来像这样:

enter image description here

3)在某种程度上。当我想将Datagrid的内容传递给我的类对象时,程序必须知道List 1现在包含2个项目,但是List 2 - 1个项目。

我怎样才能以最佳方式执行此类功能?

2 个答案:

答案 0 :(得分:1)

这是一个样本......

public class ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<SomeItem> VmList { get; set; }
    List<SomeItem> List1 = new List<SomeItem>(); 
    List<SomeItem> List2 = new List<SomeItem>(); 
    public ViewModel()
    {
        // VmList is the item source for the grid
        VmList = new ObservableCollection<SomeItem>();
        // create two lists
        for (int i = 0; i < 10; i++)
        {
            List1.Add(new SomeItem{ID = "1", Name = "Name " + i});
        }
        for (int i = 0; i < 10; i++)
        {
            List1.Add(new SomeItem { ID = "2", Name = "Name (2) " + i });
        }
        // merge the two separate lists
        VmList.AddRange(List1);
        VmList.AddRange(List2);
        // get the view
        var lcv = CollectionViewSource.GetDefaultView(VmList);
        // apply a filter
        lcv.Filter = o =>
            {
                var someItem = o as SomeItem;
                if (someItem != null)
                {
                    return someItem.ID == "2";
                }
                return false;
            };
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
public class SomeItem:INotifyPropertyChanged
{
    private string _id;
    public string ID
    {
        [DebuggerStepThrough]
        get { return _id; }
        [DebuggerStepThrough]
        set
        {
            if (value != _id)
            {
                _id = value;
                OnPropertyChanged("ID");
            }
        }
    }
    private string _name;
    public string Name
    {
        [DebuggerStepThrough]
        get { return _name; }
        [DebuggerStepThrough]
        set
        {
            if (value != _name)
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
public static class Extensions
{
    public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> list)
    {
        foreach (T t in list)
        {
            collection.Add(t);
        }
    }
}

在此示例(设计)中,视图模型构造函数创建了两个列表,并将它们添加到绑定到数据网格的可观察集合中。

然后检索底层集合视图源并附加一个过滤器。

在您的应用程序中,过滤器将应用于按钮事件处理程序而不是Vm构造函数。这只是一个解释它是如何工作的样本。在我的原始评论中,我注意到你也可以使用LINQ zip操作符,但我包含了一个扩展方法,目前可能更有价值。它被称为“AddRange”。

此方法允许您将两个列表作为单个集合呈现,同时在幕后保持其独立的标识。它还显示了如何使用过滤器。

Collection View Source的文档位于http://msdn.microsoft.com/en-us/library/System.Windows.Data.CollectionViewSource.aspx

答案 1 :(得分:1)

您可以使用CompositeCollection,它可以轻松绑定多个集合 CompositeCollection没有DataContext因此,如果您要对其中一个集合进行数据绑定,则必须使用所需的DataContext引用FrameworkElement。 例如,你可以创建CollectionViewSource,绑定是这样的来源:

<DataGrid.ItemsSource>
    <CompositeCollection>
       <CollectionContainer Collection="{Binding Source={StaticResource Collection1}}" />
       <CollectionContainer Collection="{Binding Source={StaticResource Collection2}}"/>            
     </CompositeCollection>     
</DataGrid.ItemsSource>