C# 层次结构不会在视图中更新
我基本上有这个XAML和ViewModel:C# 层次结构不会在视图中更新,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我基本上有这个XAML和ViewModel: <ResourceDictionary> <DataTemplate DataType="{x:Type bizzTypes:WindowsDirectory}" x:Key="directory"> <Expander Header="{Binding Path=Name}" Expanded="Expander_Expanded" Cursor="Hand"
<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));
}
}
}
公共类窗口目录
{
私有observeCollection_目录{get;set;}
公共可观测收集目录
{
得到
{
返回_目录;
}
专用设备
{
_目录=值;
RaisePropertyChanged(目录名称));
}
}
}
如果我在呈现WPF UI之前填充数据树,它基本上是有效的。但是,每当我更新ObservableCollection目录
时,WPF UI都不会反映Obervable中所做的更改。目录不更新为RaisePropertyChanged(目录名称))代码>并且没有RaisePropertyChanged
我得到一个空的ItemsControl
有人知道为什么会发生这种情况吗?这里有一个例子,其特点是:
HierarchycalDataTemplate
- 使用
observedcollection
- 向树中添加随机元素的按钮
元素
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;
}
}
}
使用系统集合;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
命名空间WpfApp2
{
公共类目录:FileSystemElement,IEnumerable
{
公共目录(字符串名称):基(名称)
{
}
公共ICollection元素{get;}=newobserveCollection();
公共IEnumerator GetEnumerator()
{
返回元素。GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回((IEnumerable)元素);
}
公共T添加(T项),其中T:IFileSystemElement
{
元素。添加(项目);
退货项目;
}
}
}
查看
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>
使用系统;
使用System.Windows;
命名空间WpfApp2
{
公共部分类主窗口
{
公共主窗口()
{
初始化组件();
var level0=新目录(“0级”);
var level1=level0.Add(新目录(“级别1”);
var level2=level1.Add(新目录(“level2”);
var file1=level2.Add(新文件(“文件1”));
var file2=level2.Add(新文件(“文件2”));
DataContext=new[]{level0};//在树中显示根
}
private Random{get;}=new Random();
私有目录SelectedDirectory{get;set;}
private void TreeView_OnSelectedItemChanged(对象发送方,RoutedPropertyChangedEventArgs e)
{
选择Directory=e.NewValue作为目录;
Button.IsEnabled=SelectedDirectory!=null;
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
var next=随机。next(2);
开关(下一个)
{
案例0:
选择Directory.Add(新目录(“新目录”);
打破
案例1:
选择directory.Add(新文件(“新文件”);
打破
}
}
}
}
查看
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>
HierarchycalDataTemplate?是的,我也考虑过这一点,但在加载WPF窗口时,递归开始工作。只有当我尝试更新树下较深的目录
集合时,问题才会显现出来。内存中的项目会更新,但WPF UI不会更新。所以我认为HierarchycalDataTemplate可能没有必要。