在WPF MVVM中将两个集合绑定到控件的正确方法

时间:2015-01-31 20:42:18

标签: c# wpf mvvm

我有一个班级,有两个不同类型的项目集合。我想将类集合绑定到TreeView。组织ViewModel的正确方法是什么?

以下是我的猜测。

型号:

public CClassModel
{
    List<A> m_itemsA;
    List<B> m_ItemsB;
}

视图模型:

public CClassViewModel
{
    CClassModel = m_model;
    ObservableCollection<object> m_items;
    public CClassViewModel
    {
        m_model = new CClassModel();
        m_items = Merge(m_model.m_itemsA, m_model.m_itemsB);
    }
}

结合:

<TreeListControl ItemsSource="{Binding ViewModel.m_items}">

3 个答案:

答案 0 :(得分:0)

要绑定你需要拥有公共财产,目前你有私人提起。

使用

public ObservableCollection<object> Items { get; set; }

而不是

ObservableCollection<object> m_items;

答案 1 :(得分:0)

作为建议,在这种情况下使用Interface是有用的。如果AB共享某些属性,那么您可以执行以下操作:

public interface IAB
{
    string Name { get; set; }
}

public class A:IAB
{
    public string Name { get;  set; }
}
public class B:IAB
{
    public string Name { get;  set; }
}

通过这种设计,您的CClassModel课程就像这样:

public clas CClassModel
{
  public List<IAB> Items{ get;  set; }

  //...
}

现在,我建议你创建一个ViewModelBase抽象类:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    #region Property Changed Event Handler
    protected void SetPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion Property Changed Event Handler
}

此抽象类将帮助您在需要时定义新的ViewModel,例如:

public class MainViewModel:ViewModelBase
{
    private ObservableCollection<IAB> _collection;
    public ObservableCollection<IAB> Collection
    {
        get { return _collection; }
        set
        {
            if (value != this._collection)
                _collection = value;
            SetPropertyChanged("Collection");
        }
    }

    public MainViewModel()
    {
        var m_model = new CClassModel();
        Collection=new ObservableCollection<IAB>(m_model.Items);
    }
}

正如@Rafal所说,要绑定你需要在ViewModel中创建公共属性,这样你就可以公开你想要绑定的信息。

使用MVVM模式可以实现的一件事是相对于您的视图的零代码。如您所见,ViewModel的实例化在同一个View中,特别是在Resources中。要使用该实例,您需要设置根控件的DataContext属性(在本例中为Grid)。现在,您可以使用在ViewModel中定义的属性,如下所示:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wpfApplication2="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <wpfApplication2:MainViewModel x:Key="MainViewModel"/>
</Window.Resources>
<Grid DataContext="{StaticResource MainViewModel}">
    <TreeView x:Name="ABTreeView" ItemsSource="{Binding Collection}" DisplayMemberPath="Name"> </TreeView>
</Grid>

答案 2 :(得分:0)

可能是这样的:

public class A
{ 
  // add something usefull
}

public class B
{
  // add something usefull
}

public class CClassModel
{
  public List<A> m_ItemsA;
  public List<B> m_ItemsB;
}

public class APlaceHolder
{
  public string NodeName { get; set; }
  public List<A> Items { get; set; }
}

public class BPlaceHolder
{
  public string NodeName { get; set; }
  public List<B> Items { get; set; }
}

public class CClassViewModel
{
    CClassModel m_model;
    public ObservableCollection<object> Items { get; set; }

    public CClassViewModel()
    {
        m_model = new CClassModel();
        Items = new ObservableCollection<object>;

        APlaceHolder aph = new APlaceHolder();
        aph.NodeName = "A Items";
        aph.Items = m_model.m_ItemsA;
        Items.Add(aph);

        BPlaceHolder bph = new BPlaceHolder();
        bph.NodeName = "B Items";
        bph.Items = m_model.m_ItemsB;
        Items.Add(bph);
    }
}

您需要为APlaceHolder和BPlaceHolder添加HierarchicalDataTemplates,为A和B添加DataTemplates。