【问题标题】:Treeview with checkbox bind by different lists带有复选框的树视图由不同的列表绑定
【发布时间】:2011-10-01 20:07:45
【问题描述】:

我有这样的课:

public class Project
{
List<Object> list1;
List<Object> list2;
}

我想在树视图控件中显示如下:

Checkbox + "Listing1"
--> Checkbox + Object 1 of list1
--> Checkbox + Object 2 of list1
Checkbox + "Listing2"
--> Checkbox + Object 1 of list2
-->Checkbox + Object 2 of list2

我最大的问题是区分 2 个列表 + 一些额外内容:如果 list2 不包含任何对象,则可能不会显示“Listing2”标题。

有人知道我该怎么做吗?

【问题讨论】:

    标签: wpf treeview


    【解决方案1】:

    您可以通过扩展 TreeViewItem 类来创建一个类 TreeViewItemWithCheckbox,如下所示:

    public class TreeViewItemWithCheckbox : TreeViewItem
        {
            #region Variable Declaration
    
            CheckBox chkBox = new CheckBox();
            StackPanel stpContent = new StackPanel();
    
            #endregion
    
            #region Properties
    
            public string HeaderText
            {
                get { return chkBox.Content.ToString(); }
                set { chkBox.Content = value; }
            }
    
            public bool IsChecked
            {
                get { return chkBox.IsChecked.Value; }
                set { chkBox.IsChecked = value; }
            }
    
            #endregion
    
            #region Constructor
    
            public TreeViewItemWithCheckbox()
            {
                stpContent.Orientation = Orientation.Horizontal;
    
                chkBox = new CheckBox();
                chkBox.VerticalAlignment = VerticalAlignment.Center;
                chkBox.Click += new RoutedEventHandler(SetCheckboxes);
                chkBox.Margin = new Thickness(0, 0, 0, 0);
                stpContent.Children.Add(chkBox);
    
                Header = stpContent;
            }
    
            #endregion
    
            #region Event Handlers
    
            private void SetCheckboxes(object sender, RoutedEventArgs e)
            {
                TreeViewItemWithCheckbox selectedItem = ((TreeViewItemWithCheckbox)((StackPanel)((CheckBox)sender).Parent).Parent);
    
                if (selectedItem != null)
                {
                    /* Set checkboxes for all child items */
                    if (selectedItem.Items.Count > 0)
                    {
                        SetChildItemCheckboxes(selectedItem, selectedItem.IsChecked);
                    }
    
                    /* Check if all childs checked then check/uncheck parent accoringly */
                    if (selectedItem.Parent.GetType() == typeof(TreeViewItemWithCheckbox))
                    {
                        TreeViewItemWithCheckbox parentItem = (TreeViewItemWithCheckbox)selectedItem.Parent;
    
                        bool bIsAllChecked = true;
                        foreach (TreeViewItemWithCheckbox item in parentItem.Items)
                        {
                            if (!item.IsChecked)
                            {
                                bIsAllChecked = false;
                                break;
                            }
                        }
                        parentItem.IsChecked = bIsAllChecked;
                    }
                }
            }
    
            private void SetChildItemCheckboxes(TreeViewItemWithCheckbox item, bool IsChecked)
            {
                if (item.Items.Count > 0)
                {
                    foreach (TreeViewItemWithCheckbox childItem in item.Items)
                    {
                        SetChildItemCheckboxes(childItem, IsChecked);
                        item.IsChecked = IsChecked;
                    }
                }
                else
                    item.IsChecked = IsChecked;
            }
    
            #endregion
        }
    

    然后您需要从 2 个列表中添加树视图节点,如下所示:

    trvTest.Items.Clear();
    
    //Add default root element
    TreeViewItemWithCheckbox rootNode = new TreeViewItemWithCheckbox();
    rootNode.HeaderText = "Root";
    rootNode.IsExpanded = true;
    trvTest.Items.Add(rootNode);
    
    if (_project.list1.Count > 0)
    {
        TreeViewItemWithCheckbox nodeHead1 = new TreeViewItemWithCheckbox();
        nodeHead1.HeaderText = "Listing 1";
        rootNode.Items.Add(nodeHead1);
    
        TreeViewItemWithCheckbox node1;
        for (int i = 0; i < _project.list1.Count; i++)
        {
           node1 = new TreeViewItemWithCheckbox();
           node1.HeaderText = _project.list1[i].Name;
           nodeHead1.Items.Add(node1);
        }
    }
    
    if (_project.list2.Count > 0)
    {
        TreeViewItemWithCheckbox nodeHead2 = new TreeViewItemWithCheckbox();
        nodeHead2.HeaderText = "Listing 2";
        rootNode.Items.Add(nodeHead2);
    
        TreeViewItemWithCheckbox node2 = new TreeViewItemWithCheckbox();
        for (int i = 0; i < _project.list2.Count; i++)
        {
           node2 = new TreeViewItemWithCheckbox();
           node2.HeaderText = _project.list2[i].Name;
           nodeHead2.Items.Add(node2);
        }
    }
    

    【讨论】:

    • checkbox 遇到了什么问题?我已经更新了我的答案并在树视图中为复选框添加了另一个链接。该链接中有最后一个示例。
    • 它没有显示任何复选框。我尝试过使用 HierarchicalDataTemplate,但由于某种原因,这似乎没有应用
    • 两种解决方案都试过了吗?我已经从代码项目链接下载了示例项目,它对我来说工作正常。
    • 是的。如果您以编程方式设置所有项目,我不确定绑定如何工作?是的,这些例子有效;)
    • 检查我更新的答案。我添加了用于自定义树视图项的整个代码。从代码项目中删除您实现的所有模板,然后使用简单的树视图并添加我的代码。
    【解决方案2】:

    这可以在没有 TreeView 的情况下解决 - 只有 2 个 CheckBox 和 2 个 ItemsControl 以及特定的 ItemTemplate。

    我更喜欢这种解决问题的方法:

                <StackPanel>
                    <StackPanel.Resources>
                        <DataTemplate x:Key="MyTemplate">
                            <StackPanel Orientation="Horizontal">
                                <CheckBox Content="{Binding SomeProperty}" IsChecked="{Binding SomeBooleanProperty}" />
                            </StackPanel>
                        </DataTemplate>
                    </StackPanel.Resources>
                    <CheckBox Content="List number 1" />
                    <ItemsControl ItemsSource="{Binding list1}" ItemTemplate="{StaticResource MyTemplate}" />
                    <CheckBox Content="List number 2" />
                    <ItemsControl ItemsSource="{Binding list2}" ItemTemplate="{StaticResource MyTemplate}" />
                </StackPanel>
    

    至于您的 extra: 您可以将 Visibility 绑定到 Project 类中的属性,如下所示:

     public class Project
     {
          public List<Object> list1;
          public List<Object> list2;
          public Visibility Visuality
          {
              get
              {                   
                   return this.list2.Any() ? Visibility.Visible : Visibility.Colapsed;
              }
          }
     }
    

    比在代码中:

     <ItemsControl Visibility="{Binding Visuality}" ... />
     <CheckBox Visibility="{Binding Visuality}" ... />
    

    ...如果我没听错的话...

    【讨论】:

      【解决方案3】:

      如果你的第一个“列表”项目是静态的,你可以这样做

      <TreeView x:Name="tv">
          <TreeViewItem Header="Listing 1" ItemsSource="{Binding list1}"/>
          <TreeViewItem Header="Listing 2" ItemsSource="{Binding list2}"/>
      </TreeView>
      

      要隐藏没有子元素的元素,您需要一些代码。

      var view = CollectionViewSource.GetDefaultView(_project.list1);
      view.Filter = myFilter;
      view.Refresh();
      
      tv.DataContext = _project;
      

      当然对于这两个列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多