WPF:组合框中的TreeView

taor4pac  于 2023-11-21  发布在  其他
关注(0)|答案(7)|浏览(138)

我尝试在WPF中的ComboBox中放置一个TreeView,这样当组合框被删除时,用户得到的不是一个平面列表,而是一个分层列表,他们选择的任何节点都将成为ComboBox的选定值。
我已经搜索了相当多的如何实现这一点,但我能找到的最好的只有一些潜在的解决方案,因为我是可笑的新WPF,我不能使工作。
我对WPF和数据绑定有足够的了解,我可以把我的数据放到treeview中,我甚至可以把treeview放到组合框中,但是我所做的并不正确。我附上了一个截图来说明我的意思。在截图中,组合框是“打开”的,所以底部的树视图是我可以选择一个节点的地方,而“顶部”的树视图被绘制在组合框的顶部,我希望在树中显示所选节点的文本/值。
基本上,我不知道如何做的是,我如何让树视图的当前选定的节点返回其值回到组合框,然后使用它作为其选定的值?
下面是我目前使用的xaml代码:

<ComboBox Grid.Row="0" Grid.Column="1"  VerticalAlignment="Top">
        <ComboBoxItem>
            <TreeView ItemsSource="{Binding Children}" x:Name="TheTree">
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type Core:LookupGroupItem}" ItemsSource="{Binding Children}">
                        <TextBlock Text="{Binding Path=Display}"/>                            
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>
        </ComboBoxItem>
    </ComboBox>

字符串
截图:x1c 0d1x

ecr0jaav

ecr0jaav1#

对于那些仍然需要这个控件的人,我已经实现了我的Silverlight control的WPF版本。它只适用于视图模型,并要求这些视图模型实现一个特殊的接口,但除此之外,它并不难使用。
在WPF中,它看起来像这样:


的数据
您可以从这里下载源代码和示例应用程序:WpfComboboxTreeview.zip

f87krz0w

f87krz0w2#

我也有同样的问题。
在组合框中实现树视图行为的最简单方法是创建一个TextBox并将其样式化为组合框。在它旁边添加一个图像。技巧是将树视图放在弹出控件中。然后,当用户单击文本框或您选择的弹出图像时,弹出窗口将直接显示在文本框下方。
然后,当树视图项目被选中时,关闭弹出窗口并将当前选中的文本放在文本框中。
这里有一个非程式化的例子:
XAML:

<Window x:Class="ComboBoxTreeView.MainWindow"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="MainWindow" Height="350" Width="525" MouseEnter="Window_MouseEnter">
   <Grid Margin="15">
      <Grid.RowDefinitions>
         <RowDefinition Height="30" />
         <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <TextBox Grid.Row="0" x:Name="header" Width="300" Height="30" PreviewMouseDown="header_PreviewMouseDown" HorizontalAlignment="Left" />
      <Popup Grid.Row="1" x:Name="PopupTest" AllowsTransparency="True" IsOpen="False">
         <TreeView x:Name="Tree1" Initialized="Tree1_Initialized" SelectedItemChanged="Tree1_SelectedItemChanged">
            <TreeViewItem Header="Test1" x:Name="Tree1Item1">
               <TreeViewItem Header="1test1" />
               <TreeViewItem Header="2test2" />
            </TreeViewItem>
            <TreeViewItem Header="Test2" />
         </TreeView>
      </Popup>
   </Grid>
</Window>

字符串
下面是后面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ComboBoxTreeView
{
   /// <summary>
   /// Interaction logic for MainWindow.xaml
   /// </summary>
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
         InitializeComponent();
      }

      private void Window_MouseEnter(object sender, MouseEventArgs e)
      {

      }

      private void Tree1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
      {
         var trv = sender as TreeView;
         var trvItem = trv.SelectedItem as TreeViewItem;
         if (trvItem.Items.Count != 0) return;
         header.Text = trvItem.Header.ToString();
         PopupTest.IsOpen = false;
      }

      private void Tree1_Initialized(object sender, EventArgs e)
      {
         var trv = sender as TreeView;
         var trvItem = new TreeViewItem() { Header="Initialized item"};
         var trvItemSel = trv.Items[1] as TreeViewItem;
         trvItemSel.Items.Add(trvItem);
      }

      private void header_PreviewMouseDown(object sender, MouseButtonEventArgs e)
      {
         PopupTest.Placement = System.Windows.Controls.Primitives.PlacementMode.RelativePoint;
         PopupTest.VerticalOffset = header.Height;
         PopupTest.StaysOpen = true;
         PopupTest.Height = Tree1.Height;
         PopupTest.Width = header.Width;
         PopupTest.IsOpen = true;
      }
   }
}

gg58donl

gg58donl3#

您可以在树视图上使用事件处理程序来设置comboBox上的SelectedItem。
为了做到这一点,你需要像这样设置树视图的Tag属性:

<TreeView Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"  MouseDoubleClick="treeview_MouseDoubleClick" ItemsSource="{Binding Children}" x:Name="TheTree">

字符串
现在,在DoubleClick事件中,您可以在ComboBox中获得:

private void treeview_MouseDoubleClick(object sender, RoutedEventArgs e)
    {
        try
        {
            TreeView tv = sender as TreeView;
            if(tv == null)
                return;
            var cB = tv.Tag as ComboBox;
            cB.SelectedItem = tv.SelectedItem;
        }
        catch (Exception e)
        {

        }
    }


您还需要覆盖选择comboBox Item的方式,否则只要单击它,整个TreeView就会被选中。

hgtggwj0

hgtggwj04#

这个问题实际上与that one密切相关
所以你可能会发现this implementation很有帮助。这是一个带有复选框的组合框,但是你可以通过你的树了解如何将框中的文本与弹出内容分离。
它还演示了IsSelected属性应该在你的模型实体上,然后通过模型绑定回checkbox Text属性的想法。换句话说,你在折叠的组合框中显示的内容可能与内容完全无关......嗯,也许不完全,但在我的应用程序中,当用户选择组合中的几个复选框时,我可以在顶部文本框中显示逗号分隔,或者我可以显示“选择的几个选项”,或者其他。
HTH =)

fsi0uk1n

fsi0uk1n5#

这是一个古老的主题,但它可能对某些人有用。
我试着用组合框做类似的事情,我试着用popup来代替,它工作正常。要把它变成一个好的功能,它需要很多调整。

<Expander Header="TestCS">
    <Popup IsOpen="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Expander}}}">
        <TreeView ItemsSource="{Binding CSTree.CSChildren}">
            <TreeView.Resources>
                <HierarchicalDataTemplate ItemsSource="{Binding CSChildren}" DataType="{x:Type ViewModel:ObservableCS}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="16" Text="{Binding CSName}"></TextBlock>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Popup>
</Expander>

字符串

vfhzx4xs

vfhzx4xs6#

我认为你可以foreach treeViewItems然后添加到组合1by1。
在每个treeviewitemexpand事件中,将其子项追加到combobox中。
但是,将可展开项目高度设置为在一行中看起来像,例如Height = 18d。

// == Append Item into combobox =================
TreeViewItem root = new TreeViewItem();
root.Header = "item 1";
TreeViewItem t1 = new TreeViewItem();
t1.Header = "Expanding...";
root.Items.Add(t1);
// ==============================================

// == root expandind event ==============================
root.Height = 18.00d;
TreeViewItem[] items = GetRootChildren(root.Tag);
foreach(TreeViewItem item in items)
{
    combox1.Items.Add(item);
}
// ======================================================

字符串

8tntrjer

8tntrjer7#

您遇到了两个问题。(整个TreeView),这就是返回到ComboBox的基本ToggleButton的ContentPresenter中的内容。简单地使ComboBox IsEditable将停止将整个TreeView放入ComboBox的Content中,但它仍然没有选择您在TreeView中选择的项目。您必须使用在TreeView中使用SelectedItemChanged事件捕获选定项,然后将其转换为“SelectedItem”。一旦选定项并将其传递到ComboBox,请将IsDropDownOpen设置为false。

相关问题