简体   繁体   English

WPF - 选择 TreeView 内 ZFD249A0C2827225CFZ94D

[英]WPF - Programmatically set ComboBox Header/Text when selecting an item in a TreeView inside the ComboBox

In a UserControl I have a ComboBox with one hardcoded ComboBoxItem.在用户控件中,我有一个带有一个硬编码 ComboBoxItem 的 ComboBox。
The ComboBoxItem contains a TreeView. ComboBoxItem 包含一个 TreeView。
The content of the TreeView is set dynamically. TreeView的内容是动态设置的。
The content of each node in the TreeView are strings. TreeView中每个节点的内容都是字符串。
I would like to display the selected node's string in the header of the ComboBox.我想在 ComboBox 的 header 中显示所选节点的字符串。

I have tried many things and looked at many examples of TreeViews inside ComboBox, but cannot get this to work.我已经尝试了很多事情,并查看了 ComboBox 中的许多 TreeViews 示例,但无法使其正常工作。

Here is the source.这是来源。 I have removed all namespaces and other boiler-plate code.我已经删除了所有命名空间和其他样板代码。

UserControl.xaml UserControl.xaml

<UserControl x:Class="Some.Namespace.TreeViewPopup"
             xmlns:local="clr-namespace:Some.Namespace">
    <ComboBox Name="cmbPopup" Grid.Column="1"
              IsEditable="False"
              Height="25">
        <ComboBoxItem>
            <TreeView Name="tvNodes"
                      Width="200"
                      Background="Transparent"
                      BorderThickness="0"
                      SelectedItemChanged="tvNodes_SelectedItemChanged">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type local:Node}"
                                              ItemsSource="{Binding Nodes}">
                        <TextBlock Text="{Binding Name}" />
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </ComboBoxItem>
    </ComboBox>
</UserControl>

UserControl.xaml.cs UserControl.xaml.cs

public partial class TreeViewPopup : UserControl
{
    private Node SelectedNode { get; set; }

    public TreeViewPopup()
    {
        InitializeComponent();
    }

    private void tvNodes_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        SelectedNode = tvNodes.SelectedItem as Node;
        cmbPopup.Text = SelectedNode.Name;
    }

    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register
    (
        nameof(ItemsSource),
        typeof(IEnumerable),
        typeof(TreeViewPopup),
        new PropertyMetadata(null, ItemsSourceChanged)
    );

    public IEnumerable ItemsSource
    {
        get => GetValue(ItemsSourceProperty) as IEnumerable;
        set => SetValue(ItemsSourceProperty, value);
    }

    static void ItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != e.OldValue && d is TreeViewPopup)
        {
            var instance = d as TreeViewPopup;
            instance.tvNodes.ItemsSource = e.NewValue as IEnumerable;
        }
    }
}

Notice I have the property ItemsSource as custom DependencyProperty.请注意,我将属性 ItemsSource 作为自定义 DependencyProperty。 I'm going to populate the TreeView with this property.我将使用此属性填充 TreeView。 for now I just hardcode a list in MainWindow.xaml.cs to this property.现在我只是将 MainWindow.xaml.cs 中的列表硬编码到这个属性。

Node.cs节点.cs

public class Node
{
    public string Name { get; set; }
    public ObservableCollection<Node> Nodes { get; set; } = new ObservableCollection<Node>();

    public override string ToString() => Name;
}

MainWindow.xaml主窗口.xaml

<Window x:Class="Some.Namespace.MainWindow">    
    <TreeViewPopup x:Name="ptv" Height="25" />
</Window>

MainWindow.xaml.cs主窗口.xaml.cs

public partial class MainWindow: Window
{
    public PopupTreeView()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var a = new Node { Name = "A" };
        var aa = new Node { Name = "AA" };
        var ab = new Node { Name = "AB" };

        var aaa = new Node { Name = "AAA" };
        var aab = new Node { Name = "AAB" };
        var aac = new Node { Name = "AAC" };

        aa.Nodes.Add(aaa);
        aa.Nodes.Add(aab);
        aa.Nodes.Add(aac);

        a.Nodes.Add(aa);
        a.Nodes.Add(ab);

        var b = new Node { Name = "B" };

        var root = new Node { Name = "Root" };
        root.Nodes.Add(b);
        root.Nodes.Add(a);

        var nodes = new ObservableCollection<Node>();
        nodes.Add(root);

        ptv.ItemsSource = root.Nodes;
    }
}

This will give me a ComboBox with one ComboBoxItem containg the TreeView with all the nodes.这将给我一个 ComboBox 和一个包含所有节点的 TreeView 的 ComboBoxItem。
We I select a node in the TreeView the tvNodes_SelectedItemChanged is called and I can "save" the selected node.我们我在 TreeView 中的一个节点tvNodes_SelectedItemChanged调用了 tvNodes_SelectedItemChanged,我可以“保存”选定的节点。
Here I try to set the ComboBox's Text property to display the node's Name property.这里我尝试设置 ComboBox 的Text属性来显示节点的Name属性。
But this doesn't work.但这不起作用。 Instead the ComboBox displays the entire TreeView.相反,ComboBox 显示整个 TreeView。 I assume it select the entire ComboBoxItem.我假设它是 select 整个 ComboBoxItem。

Aany suggestions how to solve this? A任何建议如何解决这个问题?

/Steffe /斯蒂夫

Remove the ComboBoxItem and define an ItemTemplate :删除ComboBoxItem并定义一个ItemTemplate

<ComboBox Name="cmbPopup" Grid.Column="1"
          IsEditable="False"
          Height="25">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding}">
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ComboBoxItem}}"
                                         Value="{x:Null}">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding SelectedItem.Name}" />
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </DataTemplate>
    </ComboBox.ItemTemplate>
    <TreeView Name="tvNodes"
              Width="200"
              Background="Transparent"
              BorderThickness="0"
              SelectedItemChanged="tvNodes_SelectedItemChanged">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:Node}"
                                      ItemsSource="{Binding Nodes}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</ComboBox>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM