我基本上有这个XAML和ViewModel:
<ResourceDictionary>
<DataTemplate DataType="{x:Type bizzTypes:WindowsDirectory}" x:Key="directory">
<Expander Header="{Binding Path=Name}" Expanded="Expander_Expanded" Cursor="Hand" MouseLeftButtonDown="Expander_MouseLeftButtonDown">
<Expander.Content>
<ItemsControl ItemsSource="{Binding Path=Directories, Mode=TwoWay}" ItemTemplate="{DynamicResource ResourceKey=directory}">
</ItemsControl>
</Expander.Content>
</Expander>
</DataTemplate>
<DataTemplate DataType="{x:Type bizzTypes:WindowsDrive}" x:Key="drive">
<Expander Header="{Binding Path=PathFormattedHeader}" Cursor="Hand">
<Expander.Content>
<ItemsControl ItemsSource="{Binding Path=Directories, Mode=TwoWay}" ItemTemplate="{StaticResource ResourceKey=directory}"></ItemsControl>
</Expander.Content>
</Expander>
</DataTemplate>
</ResourceDictionary>
</Base:ControlBase.Resources>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" />
<ColumnDefinition Width="3" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<GridSplitter Grid.Column="1" Grid.Row="1" Width="3" HorizontalAlignment="Left" />
<ItemsControl Grid.Row="0" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
</ItemsControl>
<ScrollViewer HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Stretch" x:Name="Drives">
<ItemsControl ItemsSource="{Binding Path=Drives, Mode=TwoWay}" ItemTemplate="{DynamicResource drive}">
</ItemsControl>
</ScrollViewer>
我背后有这个视图模型
public class WindowsDirectory
{
private ObservableCollection<WindowsDirectory> _directories { get; set; }
public ObservableCollection<WindowsDirectory> Directories
{
get
{
return _directories;
}
private set
{
_directories = value;
RaisePropertyChanged(nameof(Directories));
}
}
}
如果在渲染WPF UI之前填充数据树,它基本上可以工作。但每当我更新ObservableCollection<WindowsDirectory> Directories
时,WPF UI都不会反映Obervable中所做的更改。该目录不会更新为RaisePropertyChanged(nameof(Directories));
而没有RaisePropertyChanged
我会得到一个空的ItemsControl
任何有关为何会发生这种情况的想法?
答案 0 :(得分:1)
以下是一个例子:
HierarchicalDataTemplate
ObservableCollection<T>
<强>元素强>
namespace WpfApp2
{
public interface IFileSystemElement
{
string Name { get; }
}
}
元素助手
namespace WpfApp2
{
public abstract class FileSystemElement : IFileSystemElement
{
protected FileSystemElement(string name)
{
Name = name;
}
public string Name { get; }
public override string ToString()
{
return Name;
}
}
}
文件强>
namespace WpfApp2
{
public class File : FileSystemElement
{
public File(string name) : base(name)
{
}
}
}
<强>目录强>
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace WpfApp2
{
public class Directory : FileSystemElement, IEnumerable<IFileSystemElement>
{
public Directory(string name) : base(name)
{
}
public ICollection<IFileSystemElement> Elements { get; } = new ObservableCollection<IFileSystemElement>();
public IEnumerator<IFileSystemElement> GetEnumerator()
{
return Elements.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) Elements).GetEnumerator();
}
public T Add<T>(T item) where T : IFileSystemElement
{
Elements.Add(item);
return item;
}
}
}
查看强>
using System;
using System.Windows;
namespace WpfApp2
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
var level0 = new Directory("level 0");
var level1 = level0.Add(new Directory("level 1"));
var level2 = level1.Add(new Directory("level 2"));
var file1 = level2.Add(new File("file 1"));
var file2 = level2.Add(new File("file 2"));
DataContext = new[] {level0}; // to show root in tree
}
private Random Random { get; } = new Random();
private Directory SelectedDirectory { get; set; }
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
SelectedDirectory = e.NewValue as Directory;
Button.IsEnabled = SelectedDirectory != null;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var next = Random.Next(2);
switch (next)
{
case 0:
SelectedDirectory.Add(new Directory("New directory"));
break;
case 1:
SelectedDirectory.Add(new File("New file"));
break;
}
}
}
}
查看强>
<Window
x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp2"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TreeView
Grid.Row="0"
ItemsSource="{Binding}"
SelectedItemChanged="TreeView_OnSelectedItemChanged">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="local:Directory" ItemsSource="{Binding Elements}">
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<Button
x:Name="Button"
Grid.Row="1"
Click="Button_Click"
Content="Button"
IsEnabled="False" />
</Grid>
</Window>