Wpf 绑定用户控件中的ObservableCollection依赖项属性

Wpf 绑定用户控件中的ObservableCollection依赖项属性,wpf,user-controls,treeview,observablecollection,dependency-properties,Wpf,User Controls,Treeview,Observablecollection,Dependency Properties,我有一个UserControl,它托管一个TreeView,该TreeView有一个从自定义类的ObservableCollection继承的自定义集合。我试图使用ViewModel中的依赖项属性绑定到一个属性,但我已经证明该过程适用于另一个属性,但在这里它不起作用 我肯定我错过了一些愚蠢的事情,但我一直在兜圈子,有人能发现我的错误吗 UserControl XAML: <UserControl x:Class="FileExplorer.TreeViewUserControl" xmln

我有一个UserControl,它托管一个TreeView,该TreeView有一个从自定义类的ObservableCollection继承的自定义集合。我试图使用ViewModel中的依赖项属性绑定到一个属性,但我已经证明该过程适用于另一个属性,但在这里它不起作用

我肯定我错过了一些愚蠢的事情,但我一直在兜圈子,有人能发现我的错误吗

UserControl XAML:

<UserControl
x:Class="FileExplorer.TreeViewUserControl"
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:fe="clr-namespace:WpfControlLibrary.FileExplorer"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="FileExplorer"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<TreeView
    BorderThickness="0"
    ItemsSource="{Binding FileSystem, RelativeSource={RelativeSource AncestorType=UserControl}}"
    TreeViewItem.Collapsed="TreeView_Collapsed"
    TreeViewItem.Expanded="TreeView_Expanded"
    VirtualizingStackPanel.IsVirtualizing="True"
    VirtualizingStackPanel.VirtualizationMode="Recycling">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type fe:FileSystemObject}" ItemsSource="{Binding Items}">
            <StackPanel Margin="0,2" Orientation="Horizontal">
                <Image
                    Width="14"
                    Margin="2"
                    Source="{Binding Image}"
                    Stretch="Fill" />
                <TextBlock
                    VerticalAlignment="Center"
                    FontSize="{StaticResource FontSizeSmall}"
                    Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
主窗口XAML:

<Window
    x:Class="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:fe="clr-namespace:WpfControlLibrary.FileExplorer;assembly=WpfControlLibrary"
    xmlns:local="clr-namespace:ModStudio.Client"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:ModStudio.Client.ViewModels"
    Title="MainWindow"
    d:DesignHeight="600"
    d:DesignWidth="800"
    WindowStartupLocation="CenterOwner"
    WindowState="Maximized"
    mc:Ignorable="d">

    <Window.Resources>
        <vm:MainWindowViewModel x:Key="MainWindowViewModel" />
    </Window.Resources>

    <Grid>
        <fe:TreeViewUserControl DataContext="{StaticResource MainWindowViewModel}" FileSystem="{Binding ApplicationExplorer}" />
    </Grid>
</Window>
主窗口将其DataContext设置为代码隐藏中ViewModel的新实例。MainWindowViewModel有一个名为ApplicationExplorer的属性,它是FileSystemObjectCollection的实例。如前所述,FileSystemObject集合继承自FileSystemObject的ObservableCollection。FileSystemObject实现INotifyPropertyChanged。如果更改ApplicationExplorer属性,控件将保持空白

我有意省略了这里的一些代码,但如果需要,可以添加它们。

不要在UserControl中设置DataContext,即删除此行:

Me.DataContext = Me
当您明确地像这样设置DataContext时,您会断开继承链,这意味着绑定到窗口中的ApplicationExplorer属性不再有效:

<fe:TreeViewUserControl DataContext="{StaticResource MainWindowViewModel}" 
                        FileSystem="{Binding ApplicationExplorer}" />

我做了3个改变,让它工作了

已将OnProperty更改为ApplicationExplorer:

Public Property ApplicationExplorer As FileSystemObjectCollection
    Get
        Return _applicationExplorer
    End Get
    Set(value As FileSystemObjectCollection)
        _applicationExplorer = value
        OnPropertyChanged(NameOf(ApplicationExplorer))
    End Set
End Property
已更新UserControl中的绑定:

    Namespace FileExplorer
    Public Class TreeViewUserControl
        Inherits UserControl

#Region "Constructors"
        Public Sub New()

            ' This call is required by the designer.
            InitializeComponent()

            ' Add any initialization after the InitializeComponent() call.
            Me.DataContext = Me
        End Sub

#End Region

#Region "Properties"

        Public Shared ReadOnly FileSystemProperty As DependencyProperty = DependencyProperty.Register("FileSystem", GetType(FileSystemObjectCollection), GetType(TreeViewUserControl))

        Public Property FileSystem As FileSystemObjectCollection
            Get
                Return CType(GetValue(FileSystemProperty), FileSystemObjectCollection)
            End Get
            Set(ByVal value As FileSystemObjectCollection)
                SetValue(FileSystemProperty, value)
                FileExplorer.UpdateLayout()
            End Set
        End Property

#End Region

   Private Function GetFileSystemInfo(ByVal root As String) As FileSystemObjectCollection
        Dim items As New FileSystemObjectCollection

        ' Parse all the directories at the path
        For Each dir As String In Directory.GetDirectories(root)
            items.Add(New FileSystemObject(dir, root))
        Next

        ' Parse all the file at the path
        For Each file As String In Directory.GetFiles(root)
            items.Add(New FileSystemObject(file, root))
        Next

        Return items
    End Function

    Private Sub TreeView_Collapsed(sender As Object, e As RoutedEventArgs)
        Dim node As TreeViewItem = CType(e.OriginalSource, TreeViewItem)
        Dim fs As FileSystemObject = CType(node.DataContext, FileSystemObject)
        fs.Clear()
    End Sub

    Private Sub TreeView_Expanded(sender As Object, e As RoutedEventArgs)
        Dim node As TreeViewItem = CType(e.OriginalSource, TreeViewItem)
        Dim fs As FileSystemObject = CType(node.DataContext, FileSystemObject)
        If Not fs.HasChildren Then Exit Sub
        fs.Items = GetFileSystemInfo(fs.FullName)
    End Sub

    End Class

End Namespace
<UserControl
    x:Class="FileExplorer.TreeViewUserControl"
    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:fe="clr-namespace:WpfControlLibrary.FileExplorer"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Name="FileExplorer"
    d:DesignHeight="300"
    d:DesignWidth="400"
    mc:Ignorable="d">
    <TreeView
        BorderThickness="0"
        ItemsSource="{Binding FileSystem, RelativeSource={RelativeSource AncestorType=fe:TreeViewUserControl}}"
        TreeViewItem.Collapsed="TreeView_Collapsed"
        TreeViewItem.Expanded="TreeView_Expanded"
        VirtualizingStackPanel.IsVirtualizing="True"
        VirtualizingStackPanel.VirtualizationMode="Recycling">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type fe:FileSystemObject}" ItemsSource="{Binding Items}">
                <StackPanel Margin="0,2" Orientation="Horizontal">
                    <Image
                        Width="14"
                        Margin="2"
                        Source="{Binding Image}"
                        Stretch="Fill" />
                    <TextBlock
                        VerticalAlignment="Center"
                        FontSize="12"
                        Text="{Binding Name}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</UserControl>
按照您的建议,从UserControl代码中删除了Me.DataContext=Me
谢谢,我以后会试试的。那你为什么写你的答案而不接受我的呢?