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 { return GetAllChildren(); }
set { count = GetAllChildren(); }
}
private int GetAllChildren()
{
int dd =1;
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");
}
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;
}
}
Other class:
public class OrgTreeViewModel : ViewModelBase
{
private static OrgTreeViewModel self;
private List<OrgElementViewModel> root;
private OrgElementViewModel selected;
private ICommand selectedCommand;
private ICommand changeDisplayLevelCommand;
private int count;
private int displayLevel = -1; //display all levels by default
//the root of the visual tree
public List<OrgElementViewModel> Root
{
get
{
if (root == null)
{
root = new List<OrgElementViewModel>();
root.Add(new OrgElementViewModel(OrgChartManager.Instance().GetRoot()));
}
return root;
}
}
public int Count
{
get { return count; }
set { count = GetCountOfEveryRecursiveObjects(Root, "Children");; }??
}
public OrgElementViewModel Selected
{
get { return selected; }
set
{
selected = value;
selected.IsSelected = true;
ShowChildrenLevel(); //show only the levels chosen by the user
OnPropertyChanged("Selected");
}
}
public ICommand SelectedCommand
{
get
{
if (selectedCommand == null)
{
selectedCommand = new CommandBase(i => this.SetSelected(i), null);
}
return selectedCommand;
}
}
public ICommand ChangeDisplayLevelCommand
{
get
{
if (changeDisplayLevelCommand == null)
{
changeDisplayLevelCommand = new CommandBase(i => ChangeDisplayLevel(i), null);
}
return changeDisplayLevelCommand;
}
}
private void SetSelected(object orgElement)
{
this.Selected = orgElement as OrgElementViewModel;
}
private void ChangeDisplayLevel(object i)
{
int level;
if (int.TryParse(i.ToString(), out level))
{
this.displayLevel = level;
ShowChildrenLevel(); //show only the levels chosen by the user
}
}
private void ShowChildrenLevel()
{
if (this.Selected != null)
{
this.Selected.ShowChildrenLevel(this.displayLevel);
}
}
private OrgTreeViewModel(){}
public static OrgTreeViewModel Instance()
{
if (self == null)
self = new OrgTreeViewModel();
return self;
}
public int GetCountOfEveryRecursiveObjects(IList list, string childrenPropertyName)
{
int count = list.Count;
foreach (object item in list)
{
System.Reflection.PropertyInfo property = item.GetType().GetProperty(childrenPropertyName);
IList childList = (IList)property.GetValue(item, null);??
if (childList == null)
continue;
count += GetCountOfEveryRecursiveObjects(childList, childrenPropertyName);
}
return count;
}
}
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; }
}
My Model:
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;
}
}
I have modified Model class by including recursion method(GetAllChildren).But while running this method throws error in the line result.AddRange(GetAllChildren(parentId));