Click here to Skip to main content
15,892,575 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have one WPF tree view control which shows the Employee details in the Hierarchical way.I want to show the Employee Name and count of their direct and indirect reportees(For example If Employee C is reporting to B and B is reporting to A , then the A's count of direct and indirect reportee will be 2)
But I am able to show the count of direct reportee(1) but not count of all reportee(2).

I have bound the items source from data base as list(Root) :

My xamal:
 <TreeView x:Name="tvMain" ItemsSource="{Binding Root}" BorderThickness="0">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal">
                    <Border BorderBrush="#02747474" Background="#02000000" HorizontalAlignment="Center" Margin="0,5,0,0" VerticalAlignment="Top" BorderThickness="1,1,1,1" x:Name="AvatarPhotoBorder">
                        <Border.BitmapEffect>
                            <DropShadowBitmapEffect ShadowDepth="7" Softness="0.75"/>
                        </Border.BitmapEffect>
                        <Image x:Name="imgPicture"  Source="{Binding ImagePath}" Stretch="Uniform" VerticalAlignment="Top" Width="75" Height="60" HorizontalAlignment="Center" />
                    </Border>
                    <TextBlock VerticalAlignment="Center">            
                    <TextBlock.Text>
                        <MultiBinding StringFormat=" {0} {1}">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                    <TextBlock Text=" [Direct and Indirect reportee:" Foreground="LightGray" />
                    <TextBlock Text="{Binding Count}" Foreground="Gray"  />??
                   <---- <TextBlock Text="{Binding Children.Count}"/>---->this will give only direct reportee count

                    <TextBlock Text="]" Foreground="LightGray"  />
                    <StackPanel.Style>
                        <Style>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsSelected}" Value="true">
                                    <Setter Property="StackPanel.Background" Value="LightBlue"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </StackPanel.Style>
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
                <Setter Property="IsExpanded" Value="True"/>
                <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
            </Style>
        </TreeView.ItemContainerStyle>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectedItemChanged">
                <i:InvokeCommandAction Command="{Binding SelectedCommand}" 
                                       CommandParameter="{Binding ElementName=tvMain, Path=SelectedItem}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>
</StackPanel>

view model:

public class OrgElementViewModel : ViewModelBase
   {

       private int Id;
       private string firstName;
       private string lastName;
       private string imagePath;
       public int count;
       private ObservableCollection<OrgElementViewModel> allchildren;

       private ObservableCollection<OrgElementViewModel> children;

       private bool isSelected;

        public int Count
       {
           get {  ;
           if (allchildren == null) //not yet initialized
               return GetAllChildren();
           return count;

           }
           set { count = GetAllChildren();
           OnPropertyChanged("Count");
            }
       }

       private int GetAllChildren()
       {


           int dd = 2;
           allchildren = new ObservableCollection<OrgElementViewModel>();
           //get the list of children from Model
           foreach (Node i in OrgChartManager.Instance().GetAllChildren(this.ID))
           {
               //allchildren.Add(new OrgElementViewModel(i));

               dd = dd + 1;
           }

           return dd;
       }

       public int ID
       {
           get { return Id; }
           set { Id = value; }
       }

       public string FirstName
       {
           get { return firstName; }
           set { firstName = value; }
       }

       public string LastName
       {
           get { return lastName; }
           set { lastName = value; }
       }

       public string ImagePath
       {
           get { return imagePath; }
           set { imagePath = value; }
       }

       public bool IsSelected
       {
           get { return isSelected; }
           set
           {
               isSelected = value;
               OnPropertyChanged("IsSelected");
           }
       }

       public ObservableCollection<OrgElementViewModel> Children
       {
           get
           {
               if (children == null) //not yet initialized
                   return GetChildren();
               return children;
           }
           set
           {
               children = value;
               OnPropertyChanged("Children");
           }
       }

       internal OrgElementViewModel(Node i)
       {
           this.ID = i.Id;
           this.FirstName = i.FirstName;
           this.LastName = i.LastName;
           this.ImagePath = Path.GetFullPath("Images/" + this.ID.ToString() + ".png");
           this.Count = GetAllChildren();


       }

       internal void ShowChildrenLevel(int levelsShown)
       {
           if (levelsShown == -1) //show all levels
               this.Children = GetChildren();
           else if (levelsShown == 0)  //don't show any more levels
               this.Children = new ObservableCollection<OrgElementViewModel>();  //set as empty
           else if (levelsShown > 0)  //if a level is requested
           {
               this.Children = GetChildren();

               foreach (OrgElementViewModel i in this.Children)
                   i.ShowChildrenLevel(levelsShown - 1);  //decrement 1 for next level
           }
       }

       private ObservableCollection<OrgElementViewModel> GetChildren()
       {
           int dd = 1;

           children = new ObservableCollection<OrgElementViewModel>();
           //get the list of children from Model
           foreach (Node i in OrgChartManager.Instance().GetChildren(this.ID))
           {
               children.Add(new OrgElementViewModel(i));

           }


           return children;
       }




   }
Model class:
public   class OrgChartManager
   {
       private static OrgChartManager self;

       //orgchart stored in dictionary
       private Dictionary<int, Node> list = new Dictionary<int, Node>();

       PersonalDAL dd = new PersonalDAL();


       private OrgChartManager()
       {

           DataTable my_datatable = new DataTable();
           my_datatable = new PersonalDAL().loademp();
           int ColumnCount = my_datatable.Columns.Count;
           int i = 1;
           foreach (DataRow dr in my_datatable.Rows)
           {
               Node node = new Node
                {
                    Id = (int)dr["ID"],
                    FirstName = (string)dr["FirstName"],
                    LastName = (string)dr["LastName"],
                  ParentId = (int)dr["ParentId"]

                 };
               list.Add(i, node);
               i++;
           }


       }

       internal static OrgChartManager Instance()
       {
           if (self == null)
               self = new OrgChartManager();
           return self;
       }

       //get the root
       internal Node GetRoot()
       {
           return list[1];  //return the top root node
       }

       //get the directchildren of a node
       internal IEnumerable<Node> GetChildren(int parentId)
       {
                  return from a in list
                  where a.Value.ParentId == parentId
                       && a.Value.Id != parentId   //don't include the root, which has the same Id and ParentId
                  select a.Value;


       }
       // Recursion method to get all the childeren under purcular ID
       internal IEnumerable<Node> GetAllChildren(int parentId)
       {
                  var result = new List<Node>();
                  var employees = from a in list
                  where (a.Value.ParentId == parentId
                       && a.Value.Id != parentId)   //don't include the root, which has the same Id and ParentId
                 select a.Value;

                 foreach (var employee in employees)
                 {
                     result.Add(employee);
                     result.AddRange(GetAllChildren(parentId));
                 }

                 return result;

 //return from a in list
             //     where a.Value.ParentId == parentId
             //          && a.Value.Id != parentId   //don't include the root, which has the same Id and ParentId
             //     select a.Value;

       }




   }
My Node class:
 class Node
      {
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int ParentId { get; set; } 





}


What I have tried:

I just want to show the count of all the children on each node item(direct and indirect)Please help me .the code where I have hi lighted with ?? is where I got stuck
Posted
Updated 19-Jan-19 21:02pm
v5

1 solution

Here are a couple of things...

1. No property is exposed for the hierarchical count, you're only looking at one level of the child count

2. Your TreeView is load-on-demand, so you will need to precalculate the counts. If coming from a DB, then you can create counts via SQL; otherwise could be done via Linq.

Update: I can see that you have revised your code. OrgElementViewModel does not correctly implement INotifyPropertyChanged event notification that I assume is implemented in the ViewModelBase class. This is why the Count property is not reflecting any updates. Also, the Child count is not updated when ShowChildrenLevel i called when a Node is expanded.
 
Share this answer
 
v2
Comments
faisalthayyil 19-Jan-19 22:26pm    
I have modified Model class by including recursion method(GetAllChildren).But while running this method throws error in the line result.AddRange(GetAllChildren(parentId));
Graeme_Grant 19-Jan-19 22:29pm    
And what error would that be?
faisalthayyil 20-Jan-19 2:24am    
I have made changes for I INotifyPropertyChanged . As you said , I have implemented INotifyPropertyChanged in Viewmodelbase class.The error in the model class in GetAllChildren method "An unhandled exception of type 'System.StackOverflowException' occurred in DevLake.OrgChart.UI.exe" in the line result.AddRange(GetAllChildren(parentId)).I have noticed same method is working fine if I run with commented code in the same method for direct employee.
Graeme_Grant 20-Jan-19 3:35am    
Stack Overflow usually results from recursion. Set a breakpoint and step through your code to see what it is doing.
faisalthayyil 20-Jan-19 4:22am    
it was infinite looping when i changed result.AddRange(GetAllChildren(parentId)); to result.AddRange(GetAllChildren(employee.Id ));.it is working..now only the problem it adds 2 extra count for each node.so I have decided to deduct 2 from the result.count

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900