none
Bind treeview to single table RRS feed

  • Question

  • Hi, Excuse me as I'm a complete beginner to WPF, and only have a few years writing MS Access applications as experience.

    I'm trying to bind a treeview to a single table.  The table looks like this;
    Uid       First     Second   Third
    1          ABC     123        2009
    2          ABC     123        2008
    3          ABC     456        2009
    4          DEF      123        2009

    So the treeview should look like;
    ABC
          123
                2009
                2008
          456
                2009
    DEF
          123
                2009

    The Uid field should be the selected item.

    I've been searching online for days now and just seem to be getting more and more confused.  If anyone can point me in the right direction I'd be very grateful.

    Thanks
    Monday, May 11, 2009 11:53 AM

Answers

All replies

  • I recommend you to use the Model-View-ViewModel pattern as explained in this article:

    http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx

    Feel free to ask any question you might have.

    Cheers,
    -Sergi Díaz
    Monday, May 11, 2009 12:34 PM
  • Hi,

     

    In this scenario, you should firstly create a hierarchical data source from a flat data source like DataTable

    Bea Stollnitz has wrote a good blog article on how to group data which is not structured hierarchically:

     

    http://bea.stollnitz.com/blog/?p=18

     

    Hope this helps.

    Thanks.


    Jim Zhou -MSFT
    Tuesday, May 12, 2009 11:35 AM
  • HI, Sergi Diaz...

    Thanks for you help....

    but i have got messed uup with dat Model-View-ViewModel pattern as a beginner in WPF i could understand NOTHING from that article.

    Please, tell me how to convert my flat DataTable content to Hierarchical Data and how to Bind that to TreeView....

    i would be very thankfull to you if u could help me  with this issue....... :)

    Thanks again

    Beginner in WPF.......VENU
    Saturday, May 16, 2009 12:57 PM
  • Hi,

    In terms of  View-Model pattern, the following is a ready-to-run example, you can refer this example to show a DataTable to a TreeView.

     

    XAML code:
    <Window x:Class="WpfApplication11.Window2"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:local="clr-namespace:WpfApplication11"

        Title="Window1" Height="300" Width="300" Name="MainWindow">

        <Window.Resources>

            <local:DataTableToTreeViewSourceConverter x:Key="DataTableToTreeViewSourceConverter"/>

            <HierarchicalDataTemplate x:Key="ItemDataTemplate" ItemsSource="{Binding Path=Children}">

                <TextBlock Text="{Binding Path=Value}"/>

            </HierarchicalDataTemplate>

        </Window.Resources>

        <Grid>

            <TreeView Margin="64,21,94,41" Name="treeView1"

                      ItemTemplate="{StaticResource ItemDataTemplate}"

                      ItemsSource="{Binding ElementName=MainWindow, Path=DataTable,

                Converter={StaticResource DataTableToTreeViewSourceConverter}}"/>

        </Grid>

    </Window>

     

    In the code behind:

    using System;

    using System.Windows;

    using System.Windows.Data;

    using System.Data;

    using System.Collections.ObjectModel;

    using System.Globalization;

    namespace WpfApplication11

    {

        public partial class Window2 : Window

        {

            public Window2()

            {

                DataTable = new DataModel().Data;

                InitializeComponent();

            }

            public DataTable DataTable

            {

                get;

                set;

            }

        }

        public class DataTableToTreeViewSourceConverter : IValueConverter

        {

            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

            {

                DataTable dt = value as DataTable;

                if (dt == null)

                    throw new ArgumentException("DataSource = null");

                TreeViewItemViewModel source = new TreeViewItemViewModel(null, -1, 0);

                TreeViewItemViewModel item;

                TreeViewItemViewModel parent;

                for (int j = 0; j < dt.Rows.Count; j++)

                {

                    for (int i = 0; i < dt.Rows[j].ItemArray.Length; i++)

                    {

                        item = source.FindItem(i, dt.Rows[j][i]);

                        if (item == null)

                        {

                            parent = i == 0 ? source : source.FindItem(i - 1, dt.Rows[j][i - 1]);

                            parent.Children.Add(new TreeViewItemViewModel(parent, i, dt.Rows[j][i]));

                        }

                    }

                }

                return source.Children;

            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

            {

                throw new NotImplementedException("DataTableToTreeViewSourceConverter only support one-way binding");

            }

        }

        /// <summary>

        /// A ViewModel class acts as an adapter between a raw data object and a TreeViewItem.

        /// </summary>

        public class TreeViewItemViewModel

        {

            protected readonly TreeViewItemViewModel parent;

            protected readonly ObservableCollection<TreeViewItemViewModel> children;

            private int _depth;

            private object _value;

            public TreeViewItemViewModel(TreeViewItemViewModel parent, int depth, object value)

            {

                this.parent = parent;

                this._depth = depth;

                this._value = value;

                children = new ObservableCollection<TreeViewItemViewModel>();

            }

            public ObservableCollection<TreeViewItemViewModel> Children

            {

                get

                {

                    return children;

                }

            }

            public TreeViewItemViewModel Parent

            {

                get

                {

                    return parent;

                }

            }

            public int Depth

            {

                get

                {

                    return _depth;

                }

                set

                {

                    _depth = value;

                }

            }

            public object Value

            {

                get

                {

                    return _value;

                }

                set

                {

                    _value = value;

                }

            }

            public TreeViewItemViewModel FindItem(int depth, object value)

            {

                if (value == null)

                    return null;

                if (depth == Depth)

                {

                    return value.Equals(Value) ? this : null;

                }

                else if (depth > Depth && children.Count > 0)

                {

                    foreach (TreeViewItemViewModel child in children)

                    {

                        TreeViewItemViewModel obj = child.FindItem(depth, value);

                        if (obj != null)

                        {

                            return obj;

                        }

                    }

                }

                return null;

            }

        }

        public class DataModel

        {

            private DataTable _data;

            public DataModel()

            {

                Data = new DataTable();

                //Init DataTable

                Data.Columns.Add("A", typeof(int));

                Data.Columns.Add("B", typeof(int));

                Data.Columns.Add("C", typeof(int));

                Data.Rows.Add(1, 4, 8);

                Data.Rows.Add(1, 4, 9);

                Data.Rows.Add(1, 4, 10);

                Data.Rows.Add(1, 5, 11);

                Data.Rows.Add(1, 5, 12);

                Data.Rows.Add(1, 5, 13);

                Data.Rows.Add(2, 6, 14);

                Data.Rows.Add(2, 6, 15);

                Data.Rows.Add(2, 6, 16);

                Data.Rows.Add(2, 6, 17);

            }

            public DataTable Data

            {

                get

                {

                    return _data;

                }

                private set

                {

                    _data = value;

                }

            }

        }

    }

     

    Note that the above example is referenced from this link:
    http://topic.csdn.net/u/20081126/14/4da057ba-6e2c-4684-9f66-e6edf9ba9d39.html

     

    In addition to the above example, you can also add the TreeViewItem recursively ,like this link mentioned:
    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a0046c9e-3857-4208-93d1-2e7a4249eb25

     

    Hope this helps.

    Thanks.

     


    Jim Zhou -MSFT
    Monday, May 18, 2009 6:49 AM