Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 层次结构不会在视图中更新_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 层次结构不会在视图中更新

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"

我基本上有这个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));
       }
  }
  }
公共类窗口目录
{
私有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可能没有必要。