我是WPF的新手,我希望TreeView始终显示展开/折叠图标(节点旁边的三角形),无论节点中是否有项目。
为了始终显示它,我为没有项目结尾的节点添加了一个虚拟项目(现在,我想在代码隐藏中执行此操作):
+ Node 1
- Node 2
- Dummy Item
+ Node 3
进一步的要求是在扩展虚拟物品的节点后将其删除 为此,我删除了OnExpand中的项目:
public void OnExpand(object sender, EventArgs e)
{
...
foreach (var item in tvItems){
if (item is dummy){
tvItems.Children.Remove(item);
}
}
...
}
这个问题是,一旦节点被扩展,我就会看到空行
+ Node 1
- Node 2
<-- How to remove this line?
+ Node 3
如何删除此行,以便列表显示如下:
+ Node 1
Node 2 // there is no empty line btw Node 2 and Node 3
+ Node 3
答案 0 :(得分:1)
试试这个样本
<Window x:Class="TreeViewExample.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">
<Grid>
<Grid.Resources>
<HierarchicalDataTemplate x:Key="ChildTemplate" >
<TextBlock FontStyle="Italic" Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="NameTemplate" ItemsSource="{Binding Path=Books}"
ItemTemplate="{StaticResource ChildTemplate}" >
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" />
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView HorizontalAlignment="Left" Height="218" VerticalAlignment="Top" Width="175" Margin="76,37,0,0" ItemsSource="{Binding Standards}" ItemTemplate="{StaticResource NameTemplate}" x:Name="tv" TreeViewItem.Expanded="TreeViewItem_Expanded" />
</Grid>
这是MainWindow.cs
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
namespace TreeViewExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<Author> authors = new ObservableCollection<Author>();
public ObservableCollection<Author> Standards
{
get { return authors; }
set { authors = value; }
}
public MainWindow()
{
InitializeComponent();
this.Loaded+=MainWindow_Loaded;
this.DataContext = this;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection<Book> Books = new ObservableCollection<Book>();
Books.Add(new Book() { Id = 1, Name = "X" });
Books.Add(new Book() { Id = 2, Name = "Y" });
Books.Add(new Book() { Id = 3, Name = "Z" });
ObservableCollection<Book> Books2 = new ObservableCollection<Book>();
Books2.Add(new Book() { Id = 1, Name = "X" });
Books2.Add(new Book() { Id = 2, Name = "Y" });
Books2.Add(new Book() { Id = 3, Name = "Z" });
Standards.Add(new Author() { Name = "I", Books = Books });
Standards.Add(new Author() { Name = "II" });
Standards.Add(new Author() { Name = "III", Books = Books2 });
}
private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
{
TreeViewItem tvi = e.OriginalSource as TreeViewItem;
Author author = tvi.Header as Author;
author.Books.Clear();
}
}
public class Author
{
public string Name { get; set; }
public ObservableCollection<Book> Books { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
}
}
此示例为节点加载示例数据,每当您尝试展开项目时,子项都将被清除。 让我知道这是解决你的问题。
答案 1 :(得分:1)
最简单的方法是覆盖默认模板以禁用隐藏指标。不幸的是,你不能用两行XAML代码做到这一点,但它仍然很容易。
首先,您需要获取default TreeView template并将其复制到资源字典中。如果你没有样式字典,你可以创建一个样式字典并将所有内容放在那里(首先刷,然后是所有样式)。
其次,您需要找到隐藏按钮并将其删除的触发器(或更改为IsEnabled或您想要的任何内容):
<Trigger Property="HasItems"
Value="false">
<Setter TargetName="Expander"
Property="Visibility"
Value="Hidden" />
</Trigger>
第三,我们需要为主样式指定自定义键,以便x:Key="{x:Type TreeView}"
成为x:Key="CustomTreeViewStyle"
。
并将它用于我们的TreeView:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyTreeViewStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TreeView Style="{StaticResource CustomTreeViewStyle}" />
</Grid>
就是这样。这不是最简短的解决方案,而是一个简单的解决方案,你可以任意方式自定义它。而且您不需要创建幻像项目。
您可以在App.xaml中引用此词典,以便每个页面都可以使用它(如果需要)。另外,我在这里使用了MergedDictionary
,以防你在页面中已经有了一些资源 - 它们将在ResourceDictionary本身中使用。