c# - 如何在wpf treeview中显示所有直接和间接子成员的数量

标签 c# .net wpf xaml

我有一个 WPF TreeView 控件,它以分层方式显示员工详细信息。我想显示员工姓名和他们直接和间接报告者的数量(例如,如果员工 C 向 B 报告,B 向A , 那么 A 的直接和间接 reportee 的数量将是 2)
但我能够显示直接报告者 (1) 的数量,但不能显示所有报告者 (2) 的数量。

我已经将数据库中的项目源绑定(bind)为列表(根):

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

查看模型:

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




}

其他类:

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




}

我的节点类:

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

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int ParentId { get; set; } 





}

我的模型:

 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;

    }




}

我通过包含递归方法 (GetAllChildren) 修改了模型类。但是在运行此方法时会在行 result.AddRange(GetAllChildren(parentId)); 中抛出错误

最佳答案

如果我们认为您的树节点中有 Children 属性,我们可以使用此方法来计算所有 TreeView 项目:

    /// <summary>
    /// get count of every recursive objects
    /// </summary>
    /// <param name="list">your list</param>
    /// <param name="childrenPropertyName">your chil property</param>
    /// <returns></returns>
    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);
            if (childList == null)
                continue;
            count += GetCountOfEveryRecursiveObjects(childList, childrenPropertyName);
        }
        return count;
    }

测试:

int count = GetCountOfEveryRecursiveObjects((IList)tvMain.ItemsSource, "Children");

关于c# - 如何在wpf treeview中显示所有直接和间接子成员的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54169875/

相关文章:

c# - 在 Visual Studio 中给定一个类,如何找出包含它的 dll?

c# - 将参数传递给 backgroundWorker(用作取消按钮)

c# - 我如何并行化这种模式?

c# - 如何根据屏幕位置计算矩阵中的位置

wpf - 如果返回的值为 Null,如何使 PriorityBinding 失败?

c# - 如何使用 ADO.NET 将 ref 变量传递给 SQL 存储过程?

c# - 如何获取登录的用户ID C#

c# - ServiceController.Stop() 后服务未完全停止

c# - 读取大型文本文件(超过 400 万行)并在 .NET 中解析每一行

wpf - C# 获取从路径到某个点的所有父目录?