在WPF MVVM的树视图中显示嵌套的集合对象

在WPF MVVM的树视图中显示嵌套的集合对象,wpf,xaml,treeview,datatemplate,hierarchicaldatatemplate,Wpf,Xaml,Treeview,Datatemplate,Hierarchicaldatatemplate,我是新来的wpfmvvm,面临着一些复杂的场景。 我需要在WPF MVVM中的树状图中显示如下: TrachineTrades TrachineTrade1 TrachineOrder1 TrachineOrder2 TrachineTrade2 TrachineOrder1 TrachineOrder2 等等 但我无法创建用于TrachineTrades和Tr

我是新来的
wpfmvvm
,面临着一些复杂的场景。 我需要在
WPF MVVM
中的树状图中显示如下:

TrachineTrades

       TrachineTrade1

           TrachineOrder1

           TrachineOrder2  

       TrachineTrade2 

           TrachineOrder1

           TrachineOrder2
等等

但我无法创建用于TrachineTrades和TrachineOrders的HierarchicalDataTemplates和用于TrachineOrder的DataTemplates的XAML,以在树视图中显示集合。任何人都可以建议/显示一些代码片段,以便我可以正确显示数据(考虑到集合在本质上是嵌套的)

我有以下课程

Model Classes:
==================

    SymbolDynamicAttribute.cs

    TrachineTrades.cs

    TrachineTrade.cs

    TrachineOrders.cs

    TrachineOrder.cs

View Model Classes:
====================

    VMSymbolDynamicAttribute.cs
模型类SymbolDynamicAttribute中的代码段: 模型类TraceTrades中的代码片段: 模型类TraceOrders中的代码段: 模型类VMSymboldDynamicAttribute中的代码片段:
谢谢

考虑一下这个简单的视图模型示例,它是我从文本结构查看器中借来的。这些类表示文本元素,其中段落可能包含跨距,跨距可能包含更多跨距和运行等。子元素保留在ObservableCollection中,允许UI在集合更改时更新

    public class TextElement : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public TextElement()
        {

        }

        public virtual ObservableCollection<TextElement> Elements
        {
            get { return m_elements; }
        }

        protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        ObservableCollection<TextElement> m_elements = new ObservableCollection<TextElement>( );
    }

    public class TextRun : TextElement
    {
        public TextRun()
        {

        }

        public String Content
        {
            get { return m_content; }
            set { if (m_content != value) { OnPropertyChanged(); } }
        }

        String m_content;
    }

    public class TextParagraph : TextElement
    {
        public TextParagraph()
        {

        }
    }
公共类TextElement:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共文本元素()
{
}
公共虚拟可观测集合元素
{
获取{返回m_元素;}
}
受保护的void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]字符串propertyName=”“)
{
if(this.PropertyChanged!=null)
this.PropertyChanged(this,newpropertychangedventargs(propertyName));
}
ObservableCollection m_元素=新的ObservableCollection();
}
公共类TextRun:TextElement
{
公共文本运行()
{
}
公共字符串内容
{
获取{return m_content;}
设置{if(m_content!=value){OnPropertyChanged();}}
}
字符串m_内容;
}
公共类text段落:TextElement
{
公共文本第()段
{
}
}
要在树状视图中显示,可以执行以下操作:

    <TreeView ItemsSource="{Binding RootElement}" >

        <TreeView.Resources>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextParagraph}" ItemsSource="{Binding Elements}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Paragraph" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextSpan}" ItemsSource="{Binding Elements}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Span" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextRun}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Run " />
                    <TextBlock Text="{Binding Content}" FontWeight="Bold" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextLinebreak}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Linebreak" />
                </StackPanel>
            </HierarchicalDataTemplate>

        </TreeView.Resources>
    </TreeView>

不必让所有类都从单个基类派生,但它们可能都应该实现INotifyPropertyChanged

还可以将布尔IsExpanded和IsSelected属性包含到视图模型类中,并将它们绑定到树视图项:

<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        <Setter Property="FontWeight" Value="Normal" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="FontWeight" Value="Bold" />
            </Trigger>
        </Style.Triggers>
    </Style>
</TreeView.ItemContainerStyle>


这样就可以展开树中的项目节点,并从viewmodel中设置正确的选择状态

嗨,先天乐观主义者,谢谢你的时间和努力。它确实指引了我正确的方向,现在我能够在UI上显示收藏。谢谢……)请考虑接受它作为回答,谢谢:
public class TrachineOrders : BaseCollection<TrachineOrder>
{
    public TrachineOrders() : base()
    {

    }

}
   public class TrachineOrder
    {
        private decimal m_price;
        private string m_OrderID;
        private DateTime m_OrderPlacedTime;        
        private TRANSACTION_TYPE m_TransactionType;
        public decimal Price
        {
            get
            {
                return m_price;
            }
            set
            {
                m_price = value;
            }
        }
        public string OrderID
        {
            get
            {
                return m_OrderID;
            }
            set
            {
                m_OrderID = value;
            }
        }
        public DateTime OrderPlacedTime
        {
            get
            {
                return m_OrderPlacedTime;
            }
            set
            {
                m_OrderPlacedTime = value;
            }
        }  
        public TRANSACTION_TYPE TransactionType
        {
            get
            {
                return m_TransactionType;
            }
            set
            {
                m_TransactionType = value;
            }
        }
    }
public class VMSymbolDynamicAttribute : BaseViewModel
{
    SymbolDynamicAttribute m_sda;

    public VMSymbolDynamicAttribute()
    {

    }

    public VMSymbolDynamicAttribute(SymbolDynamicAttribute a_sda)
    {
        m_sda = a_sda;
    }

    public TrachineTrades VM_TodaysTrades
    {
        get
        {
            return m_sda.TodaysTrades;
        }
    }

}
    public class TextElement : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public TextElement()
        {

        }

        public virtual ObservableCollection<TextElement> Elements
        {
            get { return m_elements; }
        }

        protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        ObservableCollection<TextElement> m_elements = new ObservableCollection<TextElement>( );
    }

    public class TextRun : TextElement
    {
        public TextRun()
        {

        }

        public String Content
        {
            get { return m_content; }
            set { if (m_content != value) { OnPropertyChanged(); } }
        }

        String m_content;
    }

    public class TextParagraph : TextElement
    {
        public TextParagraph()
        {

        }
    }
    <TreeView ItemsSource="{Binding RootElement}" >

        <TreeView.Resources>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextParagraph}" ItemsSource="{Binding Elements}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Paragraph" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextSpan}" ItemsSource="{Binding Elements}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Span" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextRun}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Run " />
                    <TextBlock Text="{Binding Content}" FontWeight="Bold" />
                </StackPanel>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type viewmodel:TextLinebreak}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Linebreak" />
                </StackPanel>
            </HierarchicalDataTemplate>

        </TreeView.Resources>
    </TreeView>
<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        <Setter Property="FontWeight" Value="Normal" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="FontWeight" Value="Bold" />
            </Trigger>
        </Style.Triggers>
    </Style>
</TreeView.ItemContainerStyle>