C#WPF TreeView HierarchycalDataTemplate-在列表末尾回显父节点文本
我正在寻找一种使用树视图(WPF,c#)在元素列表末尾回显父节点名称的方法 我正在处理的信息列表可能很长,我希望向用户显示他们所处的“类别”,而无需向上滚动到列表顶部。我有一个HierarchycalDataTemplate,它可以进行一些简单的字体格式化,但我看不到“closing”节点放在哪里,也看不到如何获取它的文本 这是我尝试做的一个简化示例:C#WPF TreeView HierarchycalDataTemplate-在列表末尾回显父节点文本,c#,wpf,xaml,treeview,hierarchicaldatatemplate,C#,Wpf,Xaml,Treeview,Hierarchicaldatatemplate,我正在寻找一种使用树视图(WPF,c#)在元素列表末尾回显父节点名称的方法 我正在处理的信息列表可能很长,我希望向用户显示他们所处的“类别”,而无需向上滚动到列表顶部。我有一个HierarchycalDataTemplate,它可以进行一些简单的字体格式化,但我看不到“closing”节点放在哪里,也看不到如何获取它的文本 这是我尝试做的一个简化示例: 你至少可以用两种方法来做。第一种方法是重新定义整个treeview样式。你可以找到一些例子来做这件事(这个例子不能解决你的问题,但你可以得到一般
你至少可以用两种方法来做。第一种方法是重新定义整个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。当然,您可能会希望对其进行一点模板化,以添加分隔符等,但它也会为您提供一个“可单击”的轨迹
无论如何,这只是两个想法。也许它们甚至可以激发第三个灵感。感谢您的详细回复。我采用了您建议的代码隐藏方法,效果很好。