首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >充分尊重WPF MVVM,在每个节点中创建具有不同子对象的TreeView

充分尊重WPF MVVM,在每个节点中创建具有不同子对象的TreeView
EN

Stack Overflow用户
提问于 2015-09-04 10:49:46
回答 3查看 988关注 0票数 0

我希望在充分尊重Wpf的情况下创建treeView:

根//级别0 B1- Child1 // 1级 B1-1-儿童1-1/2级 B1-2-儿童1-2 B1-3- . B2- Child2 // Level1 B2-1儿童2-1/2级 B2-2儿童2-2 B2-3 .

如您所见,我有3级的TreeView。

级别0:根(总是修正)

第1级:两个孩子(总是固定的)

第2级:动态子级,它们是从两个不同的类创建的

所以,,我的问题是如何在级别2中为级别1中的每个节点创建不同的子级。

我使用了下面的代码,但在1级的父母之下,我总是有相同的孩子。

我已经看过这个网站和网站上提出的许多解决方案.但就是想不出怎么做.

我的尝试:

代码语言:javascript
复制
  public class MyViewModel 
{
    //private ReadOnlyCollection<AttributesMapDocViewModel> _attributeMapDoc;

    public object _document;

    #region Methodes




    private List<Level0ViewModel> _myDoc;

    public List<Level0ViewModel> MyDoc
    {
        get { return _myDoc; }
        set
        {
            _myDoc = value;
        }
    }

    #endregion

    #region Constructeur

    public MyViewModel()
    {


        MyDoc = new List<Level0ViewModel>()
        {
            new Level0ViewModel("Root",_document), //_document conatins data from xml file (code not shown)
        };
    }


    #endregion

}

public class Level0ViewModel : ViewModelBase
{
    private List<Level1ViewModel> _childLevel1;

    public Level0ViewModel(string name, object myObj)
    {
        ChildLeve0Name = name;
        ChildLevel1 = new List<Level1ViewModel>()
        {
            new Level1ViewModel("Child1",myObj),
            new Level1ViewModel("Child2",myObj)
        };
    }

    public List<Level1ViewModel> ChildLevel1
    {
        get
        {
            return _childLevel1;
        }
        set
        {
            SetProperty(ref _childLevel1, value, () => ChildLevel1);

        }
    }

    public string ChildLeve0Name { get; set; }
}

public class Level1ViewModel : ViewModelBase
{
    private ObservableCollection<Level2SecondTypeViewModel> _childLevel2SecondType;
    public ObservableCollection<Level2SecondTypeViewModel> ChildLevel2SecondType
    {
        get { return _childLevel2SecondType; }
        set
        {
            if (_childLevel2SecondType != value)
            {
                SetProperty(ref _childLevel2SecondType, value, () => ChildLevel2SecondType);

            }
        }
    }


    private ObservableCollection<Level2FirstTypeViewModel> _childLevel2FirstType;
    public ObservableCollection<Level2FirstTypeViewModel> ChildLevel2FirstType
    {
        get { return _childLevel2FirstType; }
        set
        {
            if (_childLevel2FirstType != value)
            {
                SetProperty(ref _childLevel2FirstType, value, () => ChildLevel2FirstType);

            }
        }
    }

    public Level1ViewModel(string name, object mapAtt)
    {
        ChildLevel1Name = name;

        ChildLevel2FirstType = new ObservableCollection<Level2FirstTypeViewModel>();
        foreach (FirstType myFirstType in mapAtt.FirstTypes)
        {
            ChildLevel2FirstType.Add(new Level2FirstTypeViewModel(myFirstType));
        }

        ChildLevel2SecondType = new ObservableCollection<Level2SecondTypeViewModel>();
        foreach (SecondType mySecondType in mapAtt.SecondTypes)
        {
            ChildLevel2SecondType.Add(new Level2SecondTypeViewModel(mySecondType));
        }

    }

    public string ChildLevel1Name
    {
        get;
        set;
    }
}

public class Level2FirstTypeViewModel : ViewModelBase
{
    public Level2FirstTypeViewModel(FirstType fType)
    {
        FirstTypeName = fType.name;
    }

    public string FirstTypeName
    {
        get;
        set;
    }
}


public class Level2SecondTypeViewModel
{
    public Level2SecondTypeViewModel(SecondType sType)
    {
        SecondTypeName = sType.name;
    }

    public string SecondTypeName
    {
        get;
        set;
    }

}




 <TreeView ItemsSource="{Binding MyDoc}" >
  <TreeView.Resources>
            <HierarchicalDataTemplate ItemsSource="{Binding MapAttDef}" DataType="{x:Type local:Level0ViewModel}">
                      <Label Content="{Binding ChildLeve0Name}"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate ItemsSource="{Binding ChildLevel2SecondType}" DataType="{x:Type local:Level1ViewModel}">
                      <Label Content="{Binding ChildLevel1Name}"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate  DataType="{x:Type local:Level2SecondTypeViewModel}">
                       <Label Content="{Binding FirstTypeName}"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate  DataType="{x:Type local:Level2FirstTypeViewModel}">
                        <Label Content="{Binding SecondTypeName}"/>
            </HierarchicalDataTemplate>




   </TreeView.Resources>

我的尝试给了我这样的东西(这不是我想要的!):

根// 0级B1- Child1 //级别1 B1-1-儿童1-1/2级 B1-2-儿童1-2 B1-3- . B2- Child2 // Level1 B2-1儿童1-1/2级 B2-2儿童1-2 B2-3 .

EN

回答 3

Stack Overflow用户

发布于 2015-09-04 11:16:07

丢弃这些属性:Level1ViewModel.ChildLevel2FirstTypeLevel1ViewModel.ChildLevel2SecondType

你需要一个孩子的收藏。此集合的项类型依赖于继承层次结构,并且应该是最近的共同祖先(最坏的情况是object),即如下所示:

代码语言:javascript
复制
public Level1ViewModel
{
    public ObservableCollection<object> ChildLevel2
    {
        // ...
    }

    // ...
}

带有这些更改的标记将如下所示:

代码语言:javascript
复制
    <!-- Level 1 -->
    <HierarchicalDataTemplate DataType="{x:Type local:Level1ViewModel}" ItemsSource="{Binding ChildLevel2}">
              <Label Content="{Binding ChildLevel1Name}"/>
    </HierarchicalDataTemplate>

    <!-- Level 1 -->
    <DataTemplate  DataType="{x:Type local:Level2FirstTypeViewModel}">
                <Label Content="{Binding SecondTypeName}"/>
    </DataTemplate>

    <DataTemplate  DataType="{x:Type local:Level2SecondTypeViewModel}">
               <Label Content="{Binding FirstTypeName}"/>
    </DataTemplate>

请注意,HierarchicalDataTemplate必须仅用于分层数据源。对于非层次结构的(如Level2FirstTypeViewModelLevel2SecondTypeViewModel),使用常规的DataTemplate

票数 0
EN

Stack Overflow用户

发布于 2015-09-04 13:06:04

代码语言:javascript
复制
public class BaseTreeViewItem<TSource, TParent> : ViewModelBase
{

    // add static field to hold selected Item
    public static BaseTreeViewItem<TSource, TParent> SelectedChild { get; set; }

    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (_isSelected == value) return;

            if (SelectedChild != null)
            {
                SelectedChild.IsSelected = false;
                SelectedChild = null;
            }

            _isSelected = value;

            if (_isSelected)
                SelectedChild = this;

            // NotifyPropertyChanged
        }
    }

    public TParent Parent
    {
        get;
        private set;
    }

    public BaseTreeViewItem(string name, TSource myObj, TParent parent)
    {
        ChildName = name;
        DataSource = myObj;
        Parent = parent;
    }


    public string ChildName { get; set; }
    public TSource DataSource { get; set; }

    public override string ToString()
    {
        return ChildName;
    }
}

// Node

public class MyTreeViewItem<TChild, TSource, TParent> : BaseTreeViewItem<TSource, TParent>, IDeleteItem
    where TParent : IDeleteItem
    where TChild : class
{


    public ObservableCollection<TChild> Children { get; set; }

    public MyTreeViewItem(string name, TSource myObj, TParent parent)
        :base(name,myObj, parent)
    {
        Children = new ObservableCollection<TChild>();
    }

    protected virtual void InitChild()
    {

    }

    public void DeleteItem(object myTreeViewItem)
    {
        Children.Remove(myTreeViewItem as TChild);
    }

    public static void DeleteSelectedItem()
    {
        if (SelectedChild != null && SelectedChild.Parent != null)
        {
            SelectedChild.Parent.DeleteItem(SelectedChild);
        }
    }


}

public class Level0ViewModel : MyTreeViewItem<Level1ViewModel, XmlDocument, IDeleteItem>
{
    protected override sealed void InitChild()
    {
        base.InitChild();
        Children.Add(new Level1ViewModel("Child1", new Level1Src(), this));
        Children.Add(new Level1ViewModel("Child2", new Level1Src(), this));
    }

    public Level0ViewModel(string name, XmlDocument myObj) :
        base(name, myObj,null)
    {
        InitChild();
    }
}

public class Level1ViewModel : MyTreeViewItem<Level2TypeViewModel, Level1Src, Level0ViewModel>
{
    public Level1ViewModel(string name, Level1Src myObj, Level0ViewModel parent)
        : base(name, myObj, parent)
    {
        InitChild();
    }

    protected override sealed void InitChild()
    {
        base.InitChild();
        foreach (FirstType myFirstType in DataSource.FirstTypes)
        {
            Children.Add(new Level2TypeViewModel(myFirstType, this));
        }

        foreach (SecondType mySecondType in DataSource.SecondTypes)
        {
            Children.Add(new Level2TypeViewModel(mySecondType, this));
        }
    }

    // Use linq if tou want child by type
    public IEnumerable<Level2TypeViewModel> ChildType1 
    {
        get
        {
            return Children.Where(item => item.DataSource is FirstType);
        }
    }

    public IEnumerable<Level2TypeViewModel> ChildType2
    {
        get
        {
            return Children.Where(item => item.DataSource is SecondType);
        }
    }
}

public class LevelType
{
    public string Name;
}

public class FirstType : LevelType
{
}

public class SecondType : LevelType
{
}

public class Level2TypeViewModel : BaseTreeViewItem<LevelType, Level1ViewModel>
{
    public Level2TypeViewModel(LevelType sType, Level1ViewModel parent)
        : base(sType.Name, sType, parent)
    {
    }
}

我的数据源是

代码语言:javascript
复制
public Level0ViewModel TreeModel
    {
        get
        {
            return new Level0ViewModel("Root", new XmlDocument());
        }
    }

用于TreeView DataTemplate

代码语言:javascript
复制
<TreeView DataContext="{Binding ElementName=UI, Path=TreeModel}">
        <TreeView.Items>
            <TreeViewItem Header="{Binding ChildName}" ItemsSource="{Binding Path=Children}" >
                <TreeViewItem.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <Label Content="{Binding ChildName}"></Label>
                    </HierarchicalDataTemplate>
                </TreeViewItem.ItemTemplate>
            </TreeViewItem>
        </TreeView.Items>

    </TreeView>

第一个treeviewItem是显示根节点。如果不想使用它,可以将数据源更改为

代码语言:javascript
复制
public MyTreeViewItem<Level0ViewModel,object> TreeModel
        {
            get
            {
                MyTreeViewItem<Level0ViewModel,object> src = new MyTreeViewItem<Level0ViewModel, object>("Root", null);
                src.Children.Add(new Level0ViewModel("toto", new XmlDocument()));
                return src;
            }
        }

和DataTemplate到

代码语言:javascript
复制
<TreeView DataContext="{Binding ElementName=UI, Path=TreeModel}" ItemsSource="{Binding Children}">
            <TreeViewItem.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                            <Label Content="{Binding ChildName}"></Label>
                        </HierarchicalDataTemplate>
                    </TreeViewItem.ItemTemplate>
 </TreeView>

采样方式

代码语言:javascript
复制
public class TreeViewItemViewModel : ViewModelBase
{

    // add static field to hold selected Item
    public static TreeViewItemViewModel SelectedChild { get; set; }
    public TreeViewItemViewModel Parent{ get; private set;}
    public string ChildName { get; set; }
    public object DataSource { get; set; }
    private readonly ObservableCollection<TreeViewItemViewModel> _children;

    public ObservableCollection<TreeViewItemViewModel> Children
    {
        get
        {
            return _children;
        }

    }


    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (_isSelected == value) return;

            if (SelectedChild != null)
            {
                SelectedChild.IsSelected = false;
                SelectedChild = null;
            }

            _isSelected = value;

            if (_isSelected)
                SelectedChild = this;

            // NotifyPropertyChanged
        }
    }


    public TreeViewItemViewModel(string name, object myObj, TreeViewItemViewModel parent)
    {
        ChildName = name;
        DataSource = myObj;
        Parent = parent;
        _children = new ObservableCollection<TreeViewItemViewModel>();
    }

    public override string ToString()
    {
        return ChildName;
    }


    protected virtual void InitChild()
    {

    }

    public void DeleteItem(TreeViewItemViewModel myTreeViewItem)
    {
        Children.Remove(myTreeViewItem);
    }

    public static void DeleteSelectedItem()
    {
        if (SelectedChild != null && SelectedChild.Parent != null)
        {
            SelectedChild.Parent.DeleteItem(SelectedChild);
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2015-09-07 12:58:35

如果视图中有一个选定的项,则可以使用此方法。

公共类TreeViewItemViewModel : ViewModelBase {

代码语言:javascript
复制
    // add static field to hold selected Item
    public static TreeViewItemViewModel SelectedChild { get; set; }
    public TreeViewItemViewModel Parent{ get; private set;}
    public string ChildName { get; set; }
    public object DataSource { get; set; }
    private readonly ObservableCollection<TreeViewItemViewModel> _children;

    public ObservableCollection<TreeViewItemViewModel> Children
    {
        get
        {
            return _children;
        }

    }


    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (_isSelected == value) return;

            if (SelectedChild != null)
            {
                SelectedChild.IsSelected = false;
                SelectedChild = null;
            }

            _isSelected = value;

            if (_isSelected)
                SelectedChild = this;

            // NotifyPropertyChanged
        }
    }


    public TreeViewItemViewModel(string name, object myObj, TreeViewItemViewModel parent)
    {
        ChildName = name;
        DataSource = myObj;
        Parent = parent;
        _children = new ObservableCollection<TreeViewItemViewModel>();
    }

    public override string ToString()
    {
        return ChildName;
    }


    protected virtual void InitChild()
    {

    }

    public void DeleteItem(TreeViewItemViewModel myTreeViewItem)
    {
        Children.Remove(myTreeViewItem);
    }

    public static void DeleteSelectedItem()
    {
        if (SelectedChild != null && SelectedChild.Parent != null)
        {
            SelectedChild.Parent.DeleteItem(SelectedChild);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32396247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档