WPF TreeView没有重绘

时间:2016-02-20 00:41:00

标签: wpf treeview

我是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

2 个答案:

答案 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本身中使用。