The creation of directory structure and data binding (TreeView, ListBox, MVVM) in WPF are implemented in many ways

When designing a data display page, you usually need multi-level directories for navigation and selection, and TreeView and ListBox are usually used. The static, dynamic and data binding methods need to be determined according to the directory structure.

1, The simplest static method: applicable to, with simple directory structure and definite quantity

Foreground code

<Window x:Class="WpfTutorialSamples.TreeView_control.TreeViewSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TreeViewSample" Height="200" Width="250">
    <Grid Margin="10">
        <TreeView>
            <TreeViewItem Header="Level 1" IsExpanded="True">
                <TreeViewItem Header="Level 2.1" />
                <TreeViewItem Header="Level 2.2" IsExpanded="True">
                    <TreeViewItem Header="Level 3.1" />
                    <TreeViewItem Header="Level 3.2" />
                </TreeViewItem>
                <TreeViewItem Header="Level 2.3" />
            </TreeViewItem>
        </TreeView>
    </Grid>
</Window>

 

effect

 

 

  Declare TreeViewItem objects directly in XAML. In the same structure we want to display them, the first tag is the child of TreeView control, and its child object is also the child tag of its parent object. To specify the text we want to display for each node, we use the Header attribute. By default, the TreeViewItem does not expand, but to show you the structure of the example, I used   Use the IsExpanded property to expand the two parent items.

When used in the background, the data of the node can be obtained through the Name property of the control.

2, Dynamically add nodes and bind data

This method is very flexible and can freely control the number of nodes, but its implementation is relatively complex.

The following is an example of the form directory in the dynamic generation year, month and day

1. First, define the data class of the node in the background (recommended in the background code of the calling page)

public class Node
    {
        //Constructor
        public Node()
        {
            this.Nodes = new List<Node>();
        }
        public int ID { get; set; }//Inner code
        public string Name { get; set; }//name
        public bool IsParent { get; set; }//Parent
        public int OwnerID { get; set; }//Upper level internal code
        public string path { get; set; }//File path
        public string month { get; set; }//Inner code
        public string day { get; set; }//Inner code
        public List<Node> Nodes { get; set; }//Node set
    }

The attributes in the class should be defined in combination with the needs of directory dynamic control and form structure. It is necessary to dynamically control the number of nodes, and the list < node > nodes node set

2. The background definition method realizes directory structure generation, node definition and data binding

Create directory structure

 List<Node> nodesList = null;
  /// <summary>
        /// Data initialization
        /// </summary>
        private void Init()
        {
            try
            {
                List<string> namey = new List<string>();
                List<string> namem = new List<string>();
                //Get year directory
                if (Directory.Exists(@"D:\HMI_Data\ArchiveData") == true)//Check year folder
                {
                    string[] Y = Directory.GetDirectories(@"D:\HMI_Data\ArchiveData");//Get folder name with path
                    for (int i = 0; i < Y.Length; i++)
                    {
                        nodesList = new List<Node>();
                        Node a = new Node();
                        string[] YY = Y[i].Split('\\');//Split path
                        a.Name = YY[YY.Length - 1];//Get folder name
                        a.ID = (i+1) * 1000;
                        a.IsParent = true;
                        a.OwnerID = 0;
                        //Get month folder name
                        string[] M = Directory.GetFileSystemEntries(Y[i]);//Get file name with path
                        //Generate monthly directory
                        for (int ii = 0; ii < M.Length; ii++)
                        {
                            Node aa = new Node();
                            string[] MM = M[ii].Split('\\');//Split path
                            string MMM = MM[MM.Length - 1];//Get folder name
                            //aa.Name = MMM.TrimEnd('.', 'd', 'b');
                            aa.Name = MMM;
                            aa.ID = (ii+1) * 100+ a.ID;
                            aa.IsParent = true;
                            aa.OwnerID = a.ID;

                            //Get file name
                            string[] D = Directory.GetFileSystemEntries(M[ii]);//Get file name with path
                            if (D != null)
                            {
                                for (int iii = 0; iii < D.Length; iii++)
                                {
                                    Node aaa = new Node();
                                    string[] DD = D[iii].Split('\\');//Split path
                                    string DDD = DD[DD.Length - 1];//Get folder name
                                    if (DDD.StartsWith("Data"))
                                    {
                                        aaa.Name = DDD.TrimEnd('.', 't', 'x', 't');
                                        aaa.ID = (iii + 1) * 10 + aa.ID;
                                        aaa.IsParent = false;
                                        aaa.OwnerID = aa.ID;
                                        aaa.path = D[iii];
                                        aa.Nodes.Add(aaa);
                                    }
                                }
                            }
                      
                            a.Nodes.Add(aa);
                        }
                        nodesList.Add(a);
                    }
                }
            }
            catch
            { MessageBox.Show("Failed to get data form directory!", "error", MessageBoxButton.OK, MessageBoxImage.Error); }
        }

Bind and create directory

 /// <summary>
         /// Binding tree
         /// </summary>
         List<Node> Bind(List<Node> nodes)
         {
             List<Node> outputList = new List<Node>();//Define node set outputList
             for (int i = 0; i<nodes.Count; i++)//Cycle by number of nodes
             {
                 if (nodes[i].OwnerID == 0)//Determine whether the root node
                 {
                     outputList.Add(nodes[i]);//Is the of the root node. Add nodes to the node set
                 }
                 else
                 {
                     FindDownward(nodes, nodes[i].OwnerID).Nodes.Add(nodes[i]);//Lookup down that is not a root node
                 }
             }
             return outputList;
         }
 
         /// <summary>
         /// Look down
         /// </summary>
         Node FindDownward(List<Node> nodes, int id)
         {
             if (nodes == null)
             {
                 return null;//Return if the node collection is empty null
             }
             for (int i = 0; i<nodes.Count; i++)//Press nodes Node set number cycle
             {
                 if (nodes[i].ID == id)//Judge node id Is it the same as the parent node
                 {
                     return nodes[i];//Is the parent node return node
                 }
                 Node node = FindDownward(nodes[i].Nodes, id);//Look down
                 if (node != null)//Node is not equal to return node
                 {
                     return node;
                 }
             }
             return null;//Return null value
         }
Call in structure function

  public main()
        {
            InitializeComponent();
            Init();
            List<Node> outputList = Bind(nodesList);// Binding tree
            this.TreeView.ItemsSource = outputList;//binding TreeView.Items data source
        }
TreeView Is the name of the foreground control
3,Foreground control calling code

 <TreeView Name="TreeView" Background="{x:Null}" Foreground="#FF60EC37" FontSize="18">
                                <TreeView.Resources>
                                    <HierarchicalDataTemplate DataType="{x:Type mode:Node}" ItemsSource="{Binding Nodes}">
                                        <StackPanel Orientation="Horizontal" Margin="0,2,0,2">
                                            <Button Content="{Binding Name}" ToolTip="{Binding Name}" Tag="{Binding Path=path}"  Background="{x:Null}" Click="Button_Click" 
                                                FontSize="18" Foreground="#FF60EC37" BorderThickness="0"
                                                Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
                                            </Button>
                                        </StackPanel>
                                    </HierarchicalDataTemplate>
                                </TreeView.Resources>
                            </TreeView>

4. Get node data and control the opening of the selected form

During the foreground call, a Button control is defined in the node Tag, and its Tag property is bound to the file path obtained in the background. At the same time, it controls the opening of the specified file in the click event

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            Button pU = sender as Button;
            if (pU.Tag.ToString() != "")
            {
                string f = pU.Tag.ToString();
            }
//Form opening control code
......................

        }

3, Dynamic add (MVVM) mode

Data binding:

Update: supplement the data binding code of TreeView control in MVVM mode.

xaml Code:

<TreeView Name="syntaxTree" ItemsSource="{Binding TreeNodes}">
                                <TreeView.ItemTemplate>
                                    <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                                        <TextBlock Text="{Binding NodeName}"/>
                                    </HierarchicalDataTemplate>
                                </TreeView.ItemTemplate>
</TreeView>

ItemsSource in TreeView is bound with a list of TreeNodes named TreeNodes, that is, list < TreeNode > TreeNodes. ChildNodes property of each node in the TreeNodes bound by ItemsSource in the hierarchical Datatemplate.

Code in ViewModel.cs (with deletion):

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private List<TreeNode> treenodes = new List<TreeNode>();
    public List<TreeNode> TreeNodes
    {
       get { return treenodes; }
       set
       {
          treenodes = value;
          if (PropertyChanged != null)
             PropertyChanged(this, new PropertyChangedEventArgs("TreeNodes"));
       }
    }

    public ViewModel()
    {
    // Nodes Is a set of nodes I have obtained
       TreeNodes = getChildNodes(0,Nodes);
    }

    private List<TreeNode> getChildNodes(int parentID, List<TreeNode> nodes)
    {
       List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
       List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
       foreach (TreeNode node in mainNodes)
          node.ChildNodes = getChildNodes(node.NodeID, otherNodes);
       return mainNodes;
    }
}

Using MVVM mode, the xaml.cs file will become very simple, and there is basically only one sentence of code:

this.DataContext = new ViewModel();

The advantage of this pattern is to separate the UI design from the back-end code and connect only through data binding. I tried it several times. It's really convenient.

 

TreeView data binding requires hierarchical data template to display hierarchical data. XAML code is as follows:

<TreeView Name="chapterTree" Grid.Column="0">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=ChildNodes}">
                    <StackPanel>
                        <Label Content="{Binding Path=NodeName}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

The ChildNodes bound by ItemsSource should be a collection type: List < TreeNode >, the NodeName attribute of TreeNode is bound in Label, and the definition of TreeNode class is as follows:

public class TreeNode
    {
        public int NodeID { get; set; }
        public int ParentID { get; set; }
        public string NodeName { get; set; }
        public List<TreeNode> ChildNodes { get; set; }
        public TreeNode()
        {
            ChildNodes = new List<TreeNode>();
        }
    }

Because it is a tree structure, TreeNode needs to have NodeID attribute and ParentID attribute, that is, the ID of a tree node itself and the ID of its parent node. Taking the directory as an example, the code in xaml.cs is as follows. First, the data is written. In my actual project, these data are queried from the DB. Here, in order to simplify, the data is directly Input.

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            InputData();
            chapterTree.ItemsSource = getNodes(0, nodes);
        }

        private List<TreeNode> nodes;
        private void InputData()
        {
            nodes = new List<TreeNode>()
            {
                new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
                new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
                new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
                new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
                new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
                new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
                new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
                new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
                new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
                new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
                new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
            };
        }
        private List<TreeNode> getNodes(int parentID, List<TreeNode> nodes)
        {
            List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
            List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
            foreach (TreeNode node in mainNodes)
                node.ChildNodes = getNodes(node.NodeID, otherNodes);
            return mainNodes;
        }
    }

It should be noted that NodeID is increasing. Each node has its own ID, and its parent ID depends on which parent node it belongs to. getNodes() is a recursive method that continuously reads the child nodes of a node. The operation results are shown in the figure:

 

Adding TreeView dynamically in the background:

At the beginning, treeview was directly used in xaml.cs without data binding. Although it was found that binding was more convenient after using data binding, this method of building treeview in the background may be used one day. Just record it.

XAML file, using a TreeView control

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="60*"/>
            <ColumnDefinition Width="100*"/>
        </Grid.ColumnDefinitions>
        <TreeView Name="chapterTree" Grid.Column="0"/>
    </Grid>

The XAML.CS file also uses the recursive method, which is to constantly create new treeviewitem controls.

public partial class DynamicTreeView : Window
    {
        public DynamicTreeView()
        {
            InitializeComponent();
            InputData();
            ShowTreeView();
        }

        private List<TreeNode> nodes;
        private void InputData()
        {
            nodes = new List<TreeNode>()
            {
                new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
                new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
                new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
                new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
                new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
                new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
                new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
                new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
                new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
                new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
                new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
            };
        }

        private void ShowTreeView()
        {
            TreeViewItem tv1 = new TreeViewItem();
            chapterTree.Items.Add(tv1);
            GetNodes(0, tv1);
        }

        private void GetNodes(int parentID, TreeViewItem tv)
        {
            List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
            foreach(var item in mainNodes)
            {
                TreeViewItem tv1 = new TreeViewItem();
                tv1.Header = item.NodeName;
                tv.Items.Add(tv1);
                GetNodes(item.NodeID, tv1);
            }
        }
    }

Running diagram: there is no convenience of data binding. At the beginning of learning WPF, I didn't think about using data binding. I always felt that as long as I could realize what I wanted, regardless of the implementation process. Later, after using it, I found that the application of using data binding to build MVVM architecture was still very good.

The data binding method of TreeView control in MVVM mode was introduced earlier. In this article, we will summarize the methods of adding events to nodes. This is wrong. In short, the effect is to click a node and the page or data corresponding to that node will appear.

Example#1: to realize the functions shown in the figure below, click the treeview name node on the left, and the detailed information of the response will appear on the right   You can bind the text attribute in the textbox of ID to the SelectedItem in treeview

First construct two classes, one is user and the other is TreeNode. User is a property of TreeNode.

 
 

Binding:

<TreeView Grid.Column="0" FontSize="15" ItemsSource="{Binding Path=Nodes}" x:Name="treeview">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                    <Label Content="{Binding Path=NodeName}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

<TextBox Text="{Binding ElementName=treeview, Path=SelectedItem.user.Key}" Canvas.Left="70" Width="200" Canvas.Top="8"
                         FontSize="15"/>

<TextBox Text="{Binding ElementName=treeview, Path=SelectedItem.user.Age}" Canvas.Left="70" Width="200" Canvas.Top="8"
                         FontSize="15"/>

The TextBox control in the above two sentences is to bind the values of SelectedItem.user.Key and SeletedItem.user.Age of the control named "treeview" in the project to the Text property. In this way, click the "Lily" node, and the corresponding information will appear on the right.

 

Example#2:

The above example is relatively simple. The second example takes the button control as a treeviewitem and binds a Command to the button control.

Scenario Description: on the left is treeview, where each treeviewitem element is a button control. Click each node, and the names of qualified students will appear in the listview in the middle. For example, the students who are Grade1 include Lucy, Tom and Lily. It's Grade2Class1. There are Sam and Jack. Click the student name in listview, and the student ID and Age information will be displayed on the right.

XAML code of TreeView section:

<TreeView Grid.Column="0" FontSize="15" ItemsSource="{Binding Path=Nodes}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                    <Button Content="{Binding NodeName}" Command="{Binding DataContext.TreeViewCommand,
                        RelativeSource={RelativeSource AncestorType=local:MainWindow}}" CommandParameter="{Binding Path=NodeID}"
                            Background="White" BorderThickness="0"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

As you can see, the TreeViewItem element has changed from Label to Button. The Button control is bound with a TreeViewCommand. Here, you need to indicate that the binding is the TreeViewCommand under the DataContext. Otherwise, the default is the TreeViewCommand property in the TreeNode type. Therefore, the following sentence is very key.

Command="{Binding DataContext.TreeViewCommand,
                        RelativeSource={RelativeSource AncestorType=local:MainWindow}}" CommandParameter="{Binding Path=NodeID}"

XAML code for ListView section:

<ListView Name="listview" Grid.Column="1" ItemsSource="{Binding Users}" IsSynchronizedWithCurrentItem="True"
                   BorderBrush="DarkGray" BorderThickness="5">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" Width="auto"/>
                </GridView>
            </ListView.View>
        </ListView>

ViewModel code:

 

Two classes, DelegateCommand and DelegateCommandEventArgs, inherit from ICommand and delegate methods.

 
 

4, Listbox (MVVM) mode: it can realize dynamic node generation and dynamically display form content through two-way data binding

design sketch

 

 

 

If the page size allows, I think it is a good choice, which is more flexible than TreeView

1. The first, of course, is to define the model class

 class DataTableModel : ViewModelBase
    {
        /// <summary>
        /// ID
        /// </summary>
        public string ID
        {
            get { return _ID; }
            set { _ID = value; }
        }
        private string _ID;

        /// <summary>
        /// DB Zone variable value
        /// </summary>
        public string dbValue
        {
            get { return _dbValue; }
            set { _dbValue = value; }
        }
        private string _dbValue;

        /// <summary>
        /// M Zone variable value
        /// </summary>
        public string mValue
        {
            get { return _mValue; }
            set { _mValue = value; }
        }
        private string _mValue;

        /// <summary>
        /// I Zone variable value
        /// </summary>
        public string iValue
        {
            get { return _iValue; }
            set { _iValue = value; }
        }
        private string _iValue;

        /// <summary>
        /// Q Zone variable value
        /// </summary>
        public string qValue
        {
            get { return _qValue; }
            set { _qValue = value; }
        }
        private string _qValue;

        /// <summary>
        /// Record time
        /// </summary>
        public string Times
        {
            get { return _Times; }
            set { _Times = value; }
        }
        private string _Times;

        /// <summary>
        /// year
        /// </summary>
        public string year
        {
            get { return _year; }
            set { _year = value; }
        }
        private string _year;

        /// <summary>
        /// month
        /// </summary>
        public string month
        {
            get { return _month; }
            set { _month = value; }
        }
        private string _month;

        /// <summary>
        /// day
        /// </summary>
        public string day
        {
            get { return _day; }
            set { _day = value; }
        }
        private string _day;

        /// <summary>
        /// data sheet
        /// </summary>
        public DataTable Data
        {
            get { return _data; }
            set { _data = value; }
        }
        private DataTable _data;

        /// <summary>
        /// Child node dataset
        /// </summary>
        public ObservableCollection<DataTableModel> DataTablePropertyList
        {
            get { return _DataTablePropertyList; }
            set
            {
                _DataTablePropertyList = value;
                //RaisePropertyChanged();
            }
        }
        private ObservableCollection<DataTableModel> _DataTablePropertyList = new ObservableCollection<DataTableModel>();
    }

2. Create view

<UserControl x:Class="PLC_Monitor_Interface.MVVM.DataTableView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:PLC_Monitor_Interface.MVVM"
             mc:Ignorable="d" 
             d:DesignHeight="685" d:DesignWidth="1280" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded">
    <UserControl.Resources>
        <Style TargetType="ListBox"/>
        <Style TargetType="ScrollBar"/>
        <!--Year catalog display style-->
        <Style x:Key="year" TargetType="ListBoxItem">
            <Setter Property="Background" Value="#FF585D5E"/>
            <Setter Property="Padding"  Value="0"/>
            <Setter Property="Margin" Value="6,5,6,5"/>
            <Setter Property="Height" Value="50"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF12273A"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/>
                            </MultiTrigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Month catalog display style-->
        <Style x:Key="month" TargetType="ListBoxItem">
            <Setter Property="Background" Value="#FF585D5E"/>
            <Setter Property="Padding"  Value="0"/>
            <Setter Property="Margin" Value="6,5,6,5"/>
            <Setter Property="Height" Value="50"/>
            <!--<EventSetter Event="Selected" Handler="RootItem_Selected"/>-->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF12273A"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/>
                            </MultiTrigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Day catalog display style-->
        <Style x:Key="day" TargetType="ListBoxItem">
            <Setter Property="Background" Value="#FF585D5E"/>
            <Setter Property="Padding"  Value="0"/>
            <Setter Property="Margin" Value="6,5,0,5"/>
            <Setter Property="Height" Value="50"/>
            <!--<EventSetter Event="Selected" Handler="RootItem_Selected"/>-->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF0D2738"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                    <Condition Property="IsSelected" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="#FF3BAABC"/>
                                <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/>
                            </MultiTrigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Tertiary catalog display style-->
        <Style x:Key="Catalogue2" TargetType="ListBoxItem">
            <Setter Property="BorderBrush" Value="#FF3BAABC"/>
            <Setter Property="BorderThickness" Value="0.5,0.25"/>
            <Setter Property="Padding"  Value="0"/>
            <Setter Property="Margin" Value="0"/>
            <!--<EventSetter Event="Selected" Handler="RootItem_Selected"/>-->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                                Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True" Height="Auto">
                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" 
                                              ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </ControlTemplate>

                </Setter.Value>
            </Setter>
        </Style>
        <!--Analog write control display style-->
        <!--<Style x:Key="InputBox" TargetType="cs:A_Write_1" BasedOn="{StaticResource {x:Type cs:A_Write_1}}">
            <Setter Property="Width" Value="100"/>
            <Setter Property="Height" Value="38"/>
            <Setter Property="Background" Value="{x:Null}"/>
            <Setter Property="BorderThickness" Value="0.8"/>
            <Setter Property="BorderBrush" Value="#FFF76D13"/>
            <Setter Property="WriteCornerRadius" Value="5"/>
            <Setter Property="FontSize" Value="16"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>-->
        <!--Primary directory data display style-->
        <Style x:Key="MyItemsControlStyle" TargetType="ItemsControl" >
            <Setter Property="Width" Value="100"/>
            <!--<Setter Property="Height" Value="38"/>-->
            <Setter Property="Background" Value="{x:Null}"/>
            <!--<Setter Property="BorderThickness" Value="0.8"/>-->
            <Setter Property="BorderBrush" Value="#FFF76D13"/>
            <Setter Property="FontSize" Value="16"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>

        <Style x:Key="RadioButtonStyle" TargetType="{x:Type RadioButton}">
            <Setter Property="FocusVisualStyle">
                <Setter.Value>
                    <Style>
                        <Setter Property="Control.Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Rectangle SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Setter.Value>
            </Setter>
            <!--<Setter Property="Margin" Value="0 0 0 0"/>
            <Setter Property="FontSize" Value="26"/>-->
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RadioButton}">
                        <Grid x:Name="templateRoot" Background="#FF585D5E" SnapsToDevicePixels="True">
                            <Border x:Name="border" 
                                    BorderBrush="Red" BorderThickness="0"  SnapsToDevicePixels="True"/>
                            <Border x:Name="bd2" />
                            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"
                                              Content="{TemplateBinding Content}" Grid.Column="0"
                                              ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" 
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                              Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="HasContent" Value="True">
                                <Setter Property="FocusVisualStyle">
                                    <Setter.Value>
                                        <Style>
                                            <Setter Property="Control.Template">
                                                <Setter.Value>
                                                    <ControlTemplate>
                                                        <Rectangle Margin="14,0,0,0" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="Padding" Value="0,0,0,0"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="true">
                                <Setter Property="Foreground" Value="White"/>
                                <Setter Property="Background" Value="#FF3BAABC" TargetName="border"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="{x:Null}"/>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="MinHeight" Value="44"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
    </UserControl.Resources>
    <Grid x:Name="cvs1" Background="#FF12273A">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <!--<ColumnDefinition Width="160"/>-->
        </Grid.ColumnDefinitions>
        <Border x:Name="border1" Margin="3,3,3,0" CornerRadius="10" BorderBrush="#FF3BAABC" BorderThickness="1,0,1,1" Background="#FF0D2738">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <Border Background="#FF3BAABC" CornerRadius="3" Margin="-1,0" Height="42" >
                    <Grid Grid.Row="1"  Margin="5,0,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="100"/>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="120"/>
                            <ColumnDefinition Width="120"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Row="0" x:Name="csh" Text="Serial number" Height="{Binding Height, ElementName=csh}"  FontFamily="Arial" FontSize="16" Foreground="#FFFDFDFA" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,5,0,0"  TextAlignment="Center" Tag="tag4390"/>
                        <TextBlock Grid.Row="0" x:Name="dqz" Text="DB Zone variable value" Height="{Binding Height, ElementName=csh}" Width="{Binding Width, ElementName=csh}" Margin="{Binding Margin, ElementName=csh}" FontFamily="Arial" FontSize="16" Foreground="#FFFDFDFA" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="1" Tag="tag4391"/>
                        <TextBlock Grid.Row="0" x:Name="mrz" Text="M Zone variable value" Height="{Binding Height, ElementName=csh}"  FontFamily="Arial" FontSize="16" Foreground="#FFFDFDFA" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,5,0,0"  TextAlignment="Center" Grid.Column="2" Tag="tag4392"/>
                        <TextBlock Grid.Row="0" x:Name="ccz" Text="I Zone variable value" Height="{Binding Height, ElementName=csh}"  FontFamily="Arial" FontSize="16" Foreground="#FFFDFDFA" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,5,0,0"  TextAlignment="Center" Grid.Column="3" Tag="tag4393"/>
                        <TextBlock Grid.Row="0" x:Name="qzfw" Text="Q Zone variable value" Height="{Binding Height, ElementName=csh}" Width="100" Margin="{Binding Margin, ElementName=csh}" FontFamily="Arial" FontSize="16" Foreground="#FFFDFDFC" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="4" Tag="tag4395"/>
                        <TextBlock Grid.Row="0" x:Name="dw" Text="Record time" Height="{Binding Height, ElementName=csh}" Width="120" Margin="{Binding Margin, ElementName=csh}" FontFamily="Arial" FontSize="16" Foreground="#FFFAFAF9" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="5" Tag="tag4394"/>
                        <TextBlock Grid.Row="0" x:Name="ms" Text="Parameter function description" Height="{Binding Height, ElementName=csh}"   FontFamily="Arial" FontSize="16" Foreground="#FFFDFDF9" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="6" Margin="10,5,0,0" Tag="tag4396"/>
                    </Grid>
                </Border>
                <ListBox x:Name="listbox" Grid.Row="2" Background="{x:Null}" BorderBrush="{x:Null}" ItemsSource="{Binding DataTable3Property.DataTablePropertyList}"  ItemContainerStyle="{StaticResource Catalogue2}"  >
                    <ListBox.ItemTemplate>
                        <DataTemplate >
                            <StackPanel Orientation="Horizontal" Height="45" Margin="0">
                                <Grid >
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="80"/>
                                        <ColumnDefinition Width="100"/>
                                        <ColumnDefinition Width="80"/>
                                        <ColumnDefinition Width="80"/>
                                        <ColumnDefinition Width="120"/>
                                        <ColumnDefinition Width="50"/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Name="aaa" Text="{Binding ID}" FontSize="16" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" />
                                    <Grid Grid.Column="1">
                                        <!--<Popup  PopupAnimation="Scroll" PlacementTarget="{Binding  ElementName=AA}" IsOpen="{Binding IsChecked,ElementName=AA}" AllowsTransparency="True" Margin="0"  Opened="pop_Opened" Closed="pop_Closed">
                                            <Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="4" Width="300" Height="360" CornerRadius="3">
                                                <cs:NumKeyBoard  IsChecked="{Binding IsChecked, ElementName=AA, Mode=TwoWay}" IsDynamicGiveTag="True"/>
                                            </Border>
                                        </Popup>
                                        <cs:A_Write_1 x:Name="AA" TagWriteText="{Binding  TagWriteText}" TagReadText="{Binding  TagReadText}"  Style="{StaticResource InputBox}" Checked="Write_Checked" IsDisplayPostfix="False"/>-->
                                    </Grid>
                                    <TextBlock Text="{Binding dbValue}" FontSize="16" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="2" />
                                    <TextBlock Text="{Binding mValue}" FontSize="16" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="3" />
                                    <TextBlock Text="{Binding iValue}" FontSize="16" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="4"/>
                                    <TextBlock Text="{Binding qValue}" FontSize="16" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Grid.Column="5"/>
                                    <TextBlock Text="{Binding Times}"  FontSize="16" TextWrapping="Wrap" Foreground="#FFFCFCF9" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,0,0" Grid.Column="6"/>
                                </Grid>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </Border>
        <Border Grid.Column="1" Margin="3,0" CornerRadius="10" BorderBrush="#FF3BAABC" BorderThickness="1">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <ListBox x:Name="day" Background="{x:Null}" BorderBrush="{x:Null}" ItemsSource="{Binding DataTable2Property.DataTablePropertyList}" SelectedItem="{Binding DataTable3Property}"
                        ItemContainerStyle="{StaticResource day}">
                    <ListBox.ItemTemplate>
                        <DataTemplate >
                            <RadioButton Style="{DynamicResource RadioButtonStyle}" 
                                     Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:DataTableView}},
                                        Path=DataContext.Select2Command,Mode=TwoWay}" 
                                     CommandParameter="{Binding}">
                                <RadioButton.IsChecked>
                                    <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=ListBoxItem}" Mode="TwoWay"/>
                                </RadioButton.IsChecked>
                                <StackPanel Width="130">
                                    <TextBlock Text="{Binding day}" Tag="{Binding Tag}" Foreground="White" FontSize="16" Padding="5,0"   HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"/>
                                </StackPanel>
                            </RadioButton>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
                <ListBox x:Name="month" Grid.Column="1" BorderBrush="{x:Null}" Background="{x:Null}"  ItemsSource="{Binding DataTable1Property.DataTablePropertyList}" SelectedItem="{Binding DataTable2Property}"
                          ItemContainerStyle="{StaticResource month}">
                    <ListBox.ItemTemplate>
                        <DataTemplate >
                            <RadioButton Style="{DynamicResource RadioButtonStyle}" 
                                     Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:DataTableView}},
                                        Path=DataContext.Select1Command,Mode=TwoWay}" 
                                     CommandParameter="{Binding}">
                                <RadioButton.IsChecked>
                                    <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=ListBoxItem}" Mode="TwoWay"/>
                                </RadioButton.IsChecked>
                                <StackPanel Width="130">
                                    <TextBlock Text ="{Binding month}" Tag="{Binding Tag}" Foreground="White" FontSize="16"  Padding="5,0" TextWrapping="Wrap"/>
                                </StackPanel>
                            </RadioButton>

                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
                <ListBox x:Name="year" Grid.Column="2" BorderBrush="{x:Null}" Background="{x:Null}"  ItemsSource="{Binding DataTablePropertyList}" SelectedItem="{Binding DataTable1Property}"
                          ItemContainerStyle="{StaticResource year}">
                    <ListBox.ItemTemplate>
                        <DataTemplate >
                            <RadioButton Style="{DynamicResource RadioButtonStyle}" 
                                     Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:DataTableView}},
                                        Path=DataContext.SelectCommand,Mode=TwoWay}" 
                                     CommandParameter="{Binding}">
                                <RadioButton.IsChecked>
                                    <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=ListBoxItem}" Mode="TwoWay"/>
                                </RadioButton.IsChecked>
                                <StackPanel Width="130">
                                    <TextBlock Text ="{Binding year}"  Foreground="White" FontSize="16"  Padding="5,0" TextWrapping="Wrap"/>
                                </StackPanel>
                            </RadioButton>

                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </Border>
    </Grid>
</UserControl>
Don't forget to add the viewModel binding in the view background
public DataTableView()
        {
            InitializeComponent();
            this.DataContext = new DataTableViewModel();

        }

3. Write viewModel control code

 class DataTableViewModel : ViewModelBase
    {
        [ImportingConstructor]
        public DataTableViewModel()
        {
            SelectCommand = new RelayCommand<DataTableModel>(t => Select(t));
            Select1Command = new RelayCommand<DataTableModel>(t => Select1(t));
            Select2Command = new RelayCommand<DataTableModel>(t => Select2(t));
            Init();
        }

        #region Command
        public RelayCommand<DataTableModel> SelectCommand { get; set; }
        public RelayCommand<DataTableModel> Select1Command { get; set; }
        public RelayCommand<DataTableModel> Select2Command { get; set; }
        #endregion

        #region Attribute set
        /// <summary>
        /// Parameter table dataset
        /// Binding for foreground controls
        /// </summary>
        public DataTableModel DataTableProperty
        {
            get { return _DataTableProperty; }
            set
            {
                _DataTableProperty = value;
                RaisePropertyChanged();
            }
        }
        private DataTableModel _DataTableProperty = new DataTableModel();
        /// <summary>
        /// Grade directory
        /// </summary>
        public DataTableModel DataTable1Property
        {
            get { return _DataTable1Property; }
            set
            {
                _DataTable1Property = value;
                RaisePropertyChanged();
            }
        }
        private DataTableModel _DataTable1Property = new DataTableModel();
        /// <summary>
        /// Monthly catalog
        /// </summary>
        public DataTableModel DataTable2Property
        {
            get { return _DataTable2Property; }
            set
            {
                _DataTable2Property = value;
                RaisePropertyChanged();
            }
        }
        private DataTableModel _DataTable2Property = new DataTableModel();

        /// <summary>
        /// Daily directory
        /// </summary>
        public DataTableModel DataTable3Property
        {
            get { return _DataTable3Property; }
            set
            {
                _DataTable3Property = value;
                RaisePropertyChanged();
            }
        }
        private DataTableModel _DataTable3Property = new DataTableModel();

        /// <summary>
        /// Model Class node dataset
        /// </summary>
        public ObservableCollection<DataTableModel> DataTablePropertyList
        {
            get { return _DataTablePropertyList; }
            set
            {
                _DataTablePropertyList = value;
                RaisePropertyChanged();
            }
        }
        private ObservableCollection<DataTableModel> _DataTablePropertyList;
        #endregion
        /// <summary>
        /// Year directory click event
        /// </summary>
        /// <param name="ColumnsName">Selected year</param>
        private void Select(DataTableModel ColumnsName)
        {
            DataTable1Property = ColumnsName;//Pass the parameters obtained from the event call to the year directory dependency attribute to trigger the foreground page refresh
            DataTable2Property = ColumnsName.DataTablePropertyList[0];
        }
        /// <summary>
        /// Form data generation
        /// </summary>
        /// <param name="ColumnsName">Show column names</param>
        private void Select1(DataTableModel ColumnsName)
        {
            DataTable2Property = ColumnsName;
            DataTable3Property = ColumnsName.DataTablePropertyList[0];
        }

        private void Select2(DataTableModel ColumnsName)
        {
            DataTable3Property = ColumnsName;
        }

        /// <summary>
        /// Data initialization
        /// </summary>
        private void Init()
        {
            try
            {
                List<string> namey = new List<string>();
                List<string> namem = new List<string>();
                //Get year directory
                if (Directory.Exists(Environment.CurrentDirectory + @"\DATA") == true)//Check year folder
                {
                    string[] Y = Directory.GetDirectories(Environment.CurrentDirectory + @"\DATA");//Get folder name with path
                    for (int i = 0; i < Y.Length; i++)
                    {
                        //string YYY = YY[YY.Length - 1];//Get folder name
                        //namey.Add(YYY);
                        DataTableModel a = new DataTableModel();
                        string[] YY = Y[i].Split('\\');//Split path
                        a.year = YY[YY.Length - 1];//Get folder name

                        //Get monthly database name
                        string[] M = Directory.GetFileSystemEntries(Y[i]);//Get file name with path
                        DataTablePropertyList = new ObservableCollection<DataTableModel>();
                        //Generate monthly directory
                        for (int ii = 0; ii < M.Length; ii++)
                        {
                            DataTableModel aa = new DataTableModel();
                            string[] MM = M[ii].Split('\\');//Split path
                            string MMM = MM[MM.Length - 1];//Get folder name
                            aa.month = MMM.TrimEnd('.', 'd', 'b');
                            DataBase DataBasea = new DataBase(@"Data Source=" + M[ii]);//instantiation  DataBase Class to make the static class connection of database function point to the database of the current month
                            //Query all database table names of the current month
                            DataTable dta = DataBase.Sqlcmd_Datareader("select name from sqlite_master where type='table' order by name");
                            for (int iii = 0; iii < dta.Rows.Count; iii++)
                            {
                                DataTableModel aaa = new DataTableModel();
                                aaa.day = dta.Rows[iii][0].ToString();
                                DataTable DT = DataBase.Sqlcmd_Datareader("select* from " + aaa.day);

                                //Generate data form
                                for (int iiii = 0; iiii < DT.Rows.Count; iiii++)
                                //for (int iiii = 0; iiii < 10; iiii++)
                                {
                                    DataTableModel aaaa = new DataTableModel();//form object 
                                    //aaaa.ID = iiii.ToString();
                                    aaaa.ID = DT.Rows[iiii][0].ToString();
                                    aaaa.dbValue = DT.Rows[iiii][1].ToString();
                                    aaaa.mValue = DT.Rows[iiii][1].ToString();
                                    aaaa.iValue = DT.Rows[iiii][2].ToString();
                                    aaaa.qValue = DT.Rows[iiii][2].ToString();
                                    aaaa.Times = DT.Rows[iiii][3].ToString();
                                    aaa.DataTablePropertyList.Add(aaaa);//The form object is added to the day object set, and the month and year are added layer by layer through a nested loop
                                }
                                aa.DataTablePropertyList.Add(aaa);
                            }
                            a.DataTablePropertyList.Add(aa);
                        }
                        DataTablePropertyList.Add(a);
                    }
                    DataTable1Property = DataTablePropertyList[0];
                    Select(DataTable1Property);
                }
            }
            catch
            { MessageBox.Show("Failed to get data form directory!", "error", MessageBoxButton.OK, MessageBoxImage.Error); }
        }
    }

 

Added by johnnyk on Wed, 01 Dec 2021 04:50:38 +0200