带有由不同列表绑定的复选框的树视图

发布于 2024-12-07 01:13:48 字数 447 浏览 0 评论 0原文

我有一个这样的类:

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

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

有人知道我该怎么做吗?

I have a class like this :

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

I want to show this in a treeview control like as follows :

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

My biggest problem is making the difference between the 2 lists + some extra : if list2 does not contain any objects, the "Listing2" header may not be shown.

Does anybody have any good idea how I can do this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柠北森屋 2024-12-14 01:13:48

您可以通过扩展 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);
    }
}

You can create one class TreeViewItemWithCheckbox by extending TreeViewItem class like below :

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
    }

Then you need to add treeview nodes from 2 list like below :

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);
    }
}
沉溺在你眼里的海 2024-12-14 01:13:48

这可以在没有 TreeView 的情况下解决 - 只需 2 个复选框和 2 个具有特定 ItemTemplate 的 ItemsControl。

我更喜欢用这种方式解决这个问题:

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

至于你的额外:,你可以将 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}" ... />

...如果我理解正确的话...

This can be solved without TreeView - Just 2 CheckBoxes and 2 ItemsControl with specific ItemTemplate.

I prefer this way of solving this problem:

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

As for your extra: you can bind Visibility to the property in your Project class, which will be looks like:

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

and than in the code:

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

...if I understand you right...

世态炎凉 2024-12-14 01:13:48

如果您的第一个“列表”项目是静态的,您可以执行类似的操作

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

当然对于这两个列表。

If your first "Listing" items are static, you can do something like this

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

To hide elements without children you need a bit of code.

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

tv.DataContext = _project;

For both lists of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文