1

I am new to WPF MVVM and am facing a bit of complex scenario. I need to Display as below in a Tree View in WPF MVVM:

TrachineTrades

       TrachineTrade1

           TrachineOrder1

           TrachineOrder2  

       TrachineTrade2 

           TrachineOrder1

           TrachineOrder2

And So On.

But I am not able to create the XAML for HierarchicalDataTemplates for TrachineTrades and TrachineOrders AND DataTemplate for TrachineOrder to display the collections in a Tree view. Can anyone please suggest/show some code snippet so that I can display the data properly (Given the fact that the collections are nested within one another in nature).

I have below classes.

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

    SymbolDynamicAttribute.cs

    TrachineTrades.cs

    TrachineTrade.cs

    TrachineOrders.cs

    TrachineOrder.cs

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

    VMSymbolDynamicAttribute.cs

Code Snippets from Model Class SymbolDynamicAttribute :

public class SymbolDynamicAttribute : BaseModel
{
    private TrachineTrades m_TodaysTrades;


    public TrachineTrades TodaysTrades
    {
        get
        {
            return m_TodaysTrades;
        }
    }
}

Code Snippets from Model Class TrachineTrades:

public class TrachineTrades : BaseCollection<TrachineTrade>
{
    public TrachineTrades() : base() { }
}

Code Snippets from Model Class TrachineTrade:

   public class TrachineTrade
    {
        private TrachineOrders m_OrdersForThisTrade;

        public TrachineTrade()
        {
            m_OrdersForThisTrade = new TrachineOrders();
        }

    }

Code Snippets from Model Class TrachineOrders:

public class TrachineOrders : BaseCollection<TrachineOrder>
{
    public TrachineOrders() : base()
    {

    }

}

Code Snippets from Model Class TrachineOrder:

   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;
            }
        }
    }

Code Snippets from Model Class VMSymbolDynamicAttribute:

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;
        }
    }

}

Thanks

1 Answer 1

1

Consider this simple view model example that I borrowed and stripped down from the text structure viewer. The classes represent text elements where paragraph may contains spans, spans may contain more spans and runs etc. Child elements are kept in ObservableCollection which allows UI to update when the collection changes.

    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()
        {

        }
    }

To display it in tree view, you can do something like this:

    <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>

It is not necessary to have all classes derived from single base, but they should probably all implement INotifyPropertyChanged.

One can also include bool IsExpanded and IsSelected properties to the view model classes and bind these to tree view items:

<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>

This makes it possible to expand item nodes in tree and set selection state right from the viewmodel.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Congenital Optimist, thank you for your time and effort. It did lead me to the right direction and now I am able to display the collection on UI. Thank you .. :)
Please consider accepting it as an answer then, thanks :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.