Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#WPF TreeView HierarchycalDataTemplate-在列表末尾回显父节点文本_C#_Wpf_Xaml_Treeview_Hierarchicaldatatemplate - Fatal编程技术网

C#WPF TreeView HierarchycalDataTemplate-在列表末尾回显父节点文本

C#WPF TreeView HierarchycalDataTemplate-在列表末尾回显父节点文本,c#,wpf,xaml,treeview,hierarchicaldatatemplate,C#,Wpf,Xaml,Treeview,Hierarchicaldatatemplate,我正在寻找一种使用树视图(WPF,c#)在元素列表末尾回显父节点名称的方法 我正在处理的信息列表可能很长,我希望向用户显示他们所处的“类别”,而无需向上滚动到列表顶部。我有一个HierarchycalDataTemplate,它可以进行一些简单的字体格式化,但我看不到“closing”节点放在哪里,也看不到如何获取它的文本 这是我尝试做的一个简化示例: 你至少可以用两种方法来做。第一种方法是重新定义整个treeview样式。你可以找到一些例子来做这件事(这个例子不能解决你的问题,但你可以得到一般

我正在寻找一种使用树视图(WPF,c#)在元素列表末尾回显父节点名称的方法

我正在处理的信息列表可能很长,我希望向用户显示他们所处的“类别”,而无需向上滚动到列表顶部。我有一个HierarchycalDataTemplate,它可以进行一些简单的字体格式化,但我看不到“closing”节点放在哪里,也看不到如何获取它的文本

这是我尝试做的一个简化示例:


你至少可以用两种方法来做。第一种方法是重新定义整个treeview样式。你可以找到一些例子来做这件事(这个例子不能解决你的问题,但你可以得到一般的想法)。这种解决方案的缺点是代码非常大,在每个系统上看起来都一样,就像WindowsXP和Windows10,因为在正常情况下每个系统都使用自己的风格

我更喜欢用另一种方式解决这样的问题。我从C代码中进行更改。例如,在您的案例中,您可以在Visual Studio Xaml visualiser中看到treeview的结构:

每个treeview项都包含一个ToggleButton,用于在网格的第一行展开和折叠。接下来是一个边框,其中包含带有项内容的TextBlock(在您的示例中,它可以是datatemplate中的另一个控件,我以TextBlock为例)。它放在同一第一行。在网格的第二行中有包含子元素的ItemsPresenter

因此,我们的目标是在网格中再添加一行,并在其中放置一个文本块

首先,将ItemContainerStyle添加到treeview并在其中设置事件处理程序:

<TreeView.ItemContainerStyle>
  <Style TargetType="{x:Type TreeViewItem}">
    <EventSetter Event="Loaded" Handler="Item_Loaded"/>
  </Style>
</TreeView.ItemContainerStyle>

然后在后面的代码中:

void Item_Loaded(object sender, RoutedEventArgs e) {
    // Find the main grid of this TreeView item.
    Grid grid = FindVisualChild<Grid>((DependencyObject) sender);

    // Add new row, because it has only 2 and we need 3
    grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

    // Get the content to put into the textblock (or another control you are using in datatemplate)
    string text = ((Node) grid.DataContext).Name;

    // I'm using TextBlock to show example, you can use your own control
    TextBlock tb = new TextBlock {
        Text = text,
        Foreground = new SolidColorBrush(Colors.Gray),
    };

    grid.Children.Add(tb);

    // Visibility of our modification depends on IsExpanded and amount of child elements. If itemcontainer is collapsed or doesn't have children, we don't show this modification.
    bool flag = false;
    grid.SizeChanged += (sender1, e1) => {
        if (flag) {
            return;
        }
        flag = true;
        tb.Visibility = grid.RowDefinitions[1].ActualHeight > 0
        ? Visibility.Visible
        : Visibility.Collapsed;
        flag = false;
    };

    // Set the position of the added part
    tb.SetValue(Grid.RowProperty, 2);
    tb.SetValue(Grid.ColumnProperty, 1);
}
void Item_加载(对象发送方,路由目标){
//查找此树视图项的主网格。
Grid Grid=FindVisualChild((DependencyObject)发送方);
//添加新行,因为它只有2个,我们需要3个
添加(新的行定义{Height=GridLength.Auto});
//获取要放入textblock(或在datatemplate中使用的其他控件)的内容
字符串文本=((节点)grid.DataContext).Name;
//我用TextBlock来展示这个例子,你们可以使用你们自己的控件
TextBlock tb=新的TextBlock{
Text=Text,
前景=新的SolidColorBrush(颜色为灰色),
};
grid.Children.Add(tb);
//修改的可见性取决于IsExpanded和子元素的数量。如果itemcontainer已折叠或没有子元素,则不显示此修改。
布尔标志=假;
grid.SizeChanged+=(发送方1,e1)=>{
国际单项体育联合会(旗){
返回;
}
flag=true;
tb.Visibility=grid.RowDefinitions[1]。实际高度>0
?可视性。可见
:能见度。倒塌;
flag=false;
};
//设置添加零件的位置
tb.SetValue(Grid.RowProperty,2);
tb.SetValue(Grid.ColumnProperty,1);
}
这不是理想的解决方案,Xaml在不同的系统上可能有所不同,因此此函数可能略有不同。我只在Windows10上检查过

FindVisualChild函数如下所示:

static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject {
    for (int i = 0 ; i < VisualTreeHelper.GetChildrenCount(obj) ; i++) {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child is T) {
            return (T) child;
        }
        T childOfChild = FindVisualChild<T>(child);
        if (childOfChild != null) {
            return childOfChild;
        }
    }
    return null;
}
静态T FindVisualChild(DependencyObject对象),其中T:DependencyObject{
for(int i=0;i
实际上,我会采取另一种方法。实际上有一些

第一种方法是简单地为父节点重新模板化TreeViewItem。考虑到它的“肉”只是一个带有公开开关的网格,一个标题的ContentPresenter(这是树中的“项”)和一个ItemsControl(其ItemsSource绑定到节点的子节点),它只是嵌套了更多的容器。只需在模板中的网格中添加第三行,插入另一个内容演示者,并将其绑定也设置为标题,就完成了。你可以用一个简单的风格就可以做到。根本不需要代码隐藏

您可以做的第二件事是添加一个完全独立的“crumbtrail”控件,以在关联树中显示选定的分支,而不是破坏树本身(实际上我一开始并不喜欢它!)。它们真的很容易做。在树中选择项时,沿层次结构向上走,将项添加到列表中,然后使用水平堆栈面板将其绑定到列表框中的ItemsPanel。当然,您可能会希望对其进行一点模板化,以添加分隔符等,但它也会为您提供一个“可单击”的轨迹


无论如何,这只是两个想法。也许它们甚至可以激发第三个灵感。

感谢您的详细回复。我采用了您建议的代码隐藏方法,效果很好。