当前位置: 首页 > 知识库问答 >
问题:

WPF:使带有树视图的UserControl的行为像香草树视图一样

钱运浩
2023-03-14

我正在学习WPF,我想我缺少一些用户控件。我将尝试用例子来演示。基本上,假设我有一个treeview,我想将标签文本绑定到treeview selectedItem。这似乎很简单:

<!-- Window.xaml -->
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="100" />
    </Grid.RowDefinitions>

    <TreeView Name="MyTreeView">
        <TreeViewItem Header="Root">
            <TreeViewItem Header="Item1"></TreeViewItem>
            <TreeViewItem Header="Item2"></TreeViewItem>
        </TreeViewItem>
    </TreeView>

    <Label Content="{Binding ElementName=MyTreeView, Path=SelectedItem.Header}" Grid.Row="1"></Label>
</Grid>

现在,为了使事情复杂化,我将在混合中添加一个用户控件。用户控件基本上是网格中的TreeView:

<!-- ExampleUserControl.xaml -->
<UserControl>
    <Grid>
        <TreeView Name="UserControlTreeView">
            <TreeViewItem Header="Root">
                <TreeViewItem Header="Item1"></TreeViewItem>
                <TreeViewItem Header="Item2"></TreeViewItem>
            </TreeViewItem>
        </TreeView>
    </Grid>
</UserControl>

其目的是用usercontrol替换上面使用的vanilla treeview,并根据所选内容更改标签内容。所以,我试着这样做:

<Window>    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <local:ExampleUserControl1 x:Name="MyUserControl">            
        </local:ExampleUserControl1>

        <Label Content="{Binding ElementName=MyUserControl, Path=SelectedItem.Header}" Grid.Row="1"></Label>
    </Grid>
</Window>

这将编译并运行,但是当我在树视图中选择项时,标签不会更改。我想我明白为什么:用户控件包含树视图,但显然不是树视图。我不确定解决这个问题的最佳方法。我能想到一个似乎有问题的方法:

  • 在代码中将属性“SelectedItem”添加到用户控件,该控件返回treeviews选定项

这将适用于一个或几个属性,但是在treeview中为每个属性执行此操作的想法似乎是对代码时间的严重浪费。有没有办法仍然使用用户控件,但使其行为像正常的TreeView?

共有3个答案

戴嘉珍
2023-03-14

你关于它为什么不起作用的推理是正确的。SseltedItem属性对Label不可见。

您可以像平常一样使用TreeView,但绑定到它的ItemsSource,而不是使用UserControl来简单地托管TreeView。例如:

<!--MainWindow.xaml-->
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
        <Grid.Resources>
        <coll:ArrayList x:Key="data">
            <TreeViewItem Header="Parent 1">
                <TreeViewItem Header="Child 1"/>
                <TreeViewItem Header="Child 2"/>
            </TreeViewItem>
            <TreeViewItem Header="Parent 2">
                <TreeViewItem Header="Child 1"/>
                <TreeViewItem Header="Child 2"/>
            </TreeViewItem>
        </coll:ArrayList>
    </Grid.Resources>

    <TreeView Grid.Row="0" ItemsSource="{StaticResource data}" x:Name="tv1"/>

    <Label Grid.Row="1" Content="{Binding ElementName=tv1, Path=SelectedItem.Header}"/>
    </Grid>
</Window>

对于这个例子,我使用的是静态资源,它不是动态的。。。但是,您所要做的就是绑定到itemsource。这是处理多个TreeView的最佳方法。

编辑:

再看一遍,我发现您更想让usercontrol表现得像一个树视图,而不仅仅是得到结果。

您不能使用UserControl完全执行您所说的操作。

您要做的是创建一个扩展treeview的新类。它不需要是用户控件。

锺宜
2023-03-14

试试下面的方法

在用户控件中创建TreeView类型的公共属性,并返回TreeView,如下所示。

    //ExampleUserControl.xaml.cs
    public TreeView UTreeView
    {
        get
        {
            return UserControlTreeView;
        }
    }

然后在窗口中使用此属性。xaml如下所示。

  <local:ExampleUserControl1 x:Name="MyUserControl">
    </local:ExampleUserControl1>

    <Label Content="{Binding ElementName=MyUserControl, Path=UTreeView.SelectedItem.Header}" Grid.Row="1"></Label>
耿学义
2023-03-14

控件不能像这样从外部访问。一种方法是在代码隐藏中为SelectedItem设置包装器属性,并从外部绑定到您已经提到的属性。

但是我建议使用UserControl的Tag属性来包含TreeView的引用,并从外部绑定到Tag属性。这样,您就不必在代码隐藏中创建多个属性。

使用x:Reference绑定到TreeView:

<UserControl Tag="{Binding Source={x:Reference UserControlTreeView}}">
    <Grid>
        <TreeView Name="UserControlTreeView">
            <TreeViewItem Header="Root">
                <TreeViewItem Header="Item1"></TreeViewItem>
                <TreeViewItem Header="Item2"></TreeViewItem>
            </TreeViewItem>
        </TreeView>
    </Grid>
</UserControl>

立即绑定标签控件:

<Label Content="{Binding ElementName=MyUserControl,
                         Path=Tag.SelectedItem.Header}"/>
 类似资料:
  • 树视图以分层视图显示文档。导航栏可让你快速地切换、插入或删除文档。 添加一个文档 在导航栏点击 或按 CTRL+N 来得到一个空白显示的文档。 输入所需的数据。 在导航栏点击 来保存文档。 【注意】如果你的集合是空的,你需要点击 来添加新字段。 编辑一个文档 前往你想编辑的文档。 点击要修改的字段名、值或类型。 在导航栏点击 来应用更改。 添加一个字段或一个项目 前往你想编辑的文档。 点击 来添加

  • 树视图以分层视图显示文档。导航栏可让你快速地切换、插入或删除文档。 添加一个文档 在导航栏点击 或按 COMMAND-+ 来得到一个空白显示的文档。 输入所需的数据。 在导航栏点击 来保存文档。 【注意】如果你的集合是空的,你需要点击 来添加新字段。 编辑一个文档 前往你想编辑的文档。 点击要修改的字段名、值或类型。 在导航栏点击 来应用更改。 添加一个字段或一个项目 前往你想编辑的文档。 点击

  • 树视图以分层视图显示文档。导航栏可让你快速地切换、插入或删除文档。 添加一个文档 在导航栏点击 或按 CTRL+N 来得到一个空白显示的文档。 输入所需的数据。 在导航栏点击 来保存文档。 【注意】如果你的集合是空的,你需要点击 来添加新字段。 编辑一个文档 前往你想编辑的文档。 点击要修改的字段名、值或类型。 在导航栏点击 来应用更改。 添加一个字段或一个项目 前往你想编辑的文档。 点击 来添加

  • 新加入WPF的我正尝试使用TreeView,它提供的灵活性给我留下了难以置信的印象。 到目前为止,我的每个treeview项目都实现了一个扩展器,这是显示每个项目更详细信息并让标题仅显示摘要的好方法。但是,这不适合叶项目,并且浪费了屏幕空间——我的treeview中的每个叶项目(其中有许多)显示的数据量相对较小。 我想要为叶项目实现的是水平包装,而不是垂直列表。设想显示一个网格或(stackpan

  • 我在我的应用程序中使用MVVM模式。我有以下(简化版)VM类: 因此,一个Module2601_VM包含几个属性,以及Module2610_VM和ComPort_VM对象的列表。 我有一个MainModule_VM类中Module2601_VM对象的列表。 我想将这个Module2601集合及其子项绑定到树状视图中,并使用以下层次结构: 网关: 网关#0 COM#1 我的问题是,我的层次结构正常,

  • 我想为我的树视图创建一个上下文菜单。TreeView XAML: 而helper:ExtendedTreeView是此类: 我使用它绑定SelectedItem并在我的ViewModel中使用它。 我的树视图有“标题”,它们是类型T_Frage它们的节点是类型T_Wertung,所以它是 T_Frage T_Wertung T_Wertung T_Wertung 我想为标题创建一个上下文菜单。因此