WPF DisplayMemberPath 仅在嵌套时启动时有效 Views/VMs
WPF DisplayMemberPath Only Works On Launch When Nesting Views/VMs
我有一个失败的 DisplayMemberPath 值。
我的项目的设置是我有一个包含 ChildView 的 ParentView(这个子视图我已经简化为这个问题失败的单个控件)。 Parent view的DataContext在VM中设置一个Parent VM,一个DataTemplate用于设置ChildView的context。该 DataTemplate 在父视图中设置。
问题:我需要显示 FileName,而不是 ListBox 中 FileInfo 对象的 FullFileName 属性 值。我已经设置了 DisplayMemberName,当我在 ChildView/UserControl 中设置为绑定时,它部分起作用。也就是说它只适用于应用程序的启动。如果我将 FileInfo 对象添加到我的 ChildVM - 它会显示在列表框中,但不会显示为 FileName。相反,我只是得到 FullFileName。
按理说我错过了触发绑定的事件,但我不完全确定我应该首先以这种方式绑定。
这是功能代码。请注意,出于这个问题的目的,我已经简化了它。您可以忽略命名约定等。
这是用户控件。它是一个包含 FileInfo 对象的列表框,我想为其设置 DisplayMemberName 为 FileInfo.FileName 值。
<UserControl x:Class="CatalogInterface.ctlDirFilesListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CatalogInterface"
xmlns:vm="clr-namespace:CatalogInterface.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="MainControlGrid">
<ListBox x:Name="FileListBox"
DisplayMemberPath="{Binding ElementName=Files, Path=Files.FileName}"
<!-- Also tried DisplayMemberPath="FileName" -->
ItemsSource="{Binding Files}"
SelectedItem="{Binding Path=SelectedFiles}"
SelectionChanged="ListBoxItem_SelectionChanged"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#FFFFFF"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="3"
BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/>
<EventSetter Event="KeyDown" Handler="ListBoxItem_KeyDown"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</UserControl>
这是我的包含 UserControl 的 MainWindo 视图:
<Window x:Name="FCTWindow" x:Class="CatalogInterface.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CatalogInterface"
xmlns:vm="clr-namespace:CatalogInterface.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="532">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<!--#region Body Left Side Grid-->
<Grid x:Name="BodyGridLeft" Grid.Row="0" Grid.Column="0">
<UserControl Content="{Binding DirFilesViewModel}">
<UserControl.ContentTemplate>
<DataTemplate>
<local:ctlDirFilesListBox />
</DataTemplate>
</UserControl.ContentTemplate>
</UserControl>
</Grid>
<!--#endregion Body Left Side-->
</Window>
这是 UserControl 的 VM(用户控件实际上是我为此问题简化的更复杂的子视图的一部分)在 VM 中,当调用 OnPublishDirFiles() 时更新列表框:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
namespace CatalogInterface.ViewModels
{
public class DirFilesViewModel : ViewModelBase<DirFilesModel>
{
private object _selectedFiles;
private Messenger _messenger;
public object SelectedFiles
{
get { return _selectedFiles; }
set {
SetProperty<object>(ref _selectedFiles, value);
_messenger.SendMessage(this, "DirFilesListBox_SelectedDocumentChanged", _selectedFiles);
}
}
public ObservableCollection<FileInfo> Files { get; set; }
private DirFilesModel _model;
public DirFilesViewModel()
{
_model = new DirFilesModel();
Files = new ObservableCollection<FileInfo>();
this.OnPublishDirFiles(this, new MessageEventArgs("s", "o"));
_messenger = Messenger.Set_Messenger();
_messenger.Register(OnPublishDirFiles, "PublishDirFiles");
}
protected virtual void OnPublishDirFiles(object source, MessageEventArgs e)
{
PublishDirFiles();
}
private void PublishDirFiles()
{
if (Files == null) { } //raise NullArgumentException
Files.Clear();
foreach (FileInfo f in _model.Files) Files.Add(f);
OnPropertyChanged("Files.FileName");
}
}
}
不就是DisplayMemberPath="Name"
吗?我没有看到实际的 "FileName" 属性。有 Name
和 FullName
。
我有一个失败的 DisplayMemberPath 值。
我的项目的设置是我有一个包含 ChildView 的 ParentView(这个子视图我已经简化为这个问题失败的单个控件)。 Parent view的DataContext在VM中设置一个Parent VM,一个DataTemplate用于设置ChildView的context。该 DataTemplate 在父视图中设置。
问题:我需要显示 FileName,而不是 ListBox 中 FileInfo 对象的 FullFileName 属性 值。我已经设置了 DisplayMemberName,当我在 ChildView/UserControl 中设置为绑定时,它部分起作用。也就是说它只适用于应用程序的启动。如果我将 FileInfo 对象添加到我的 ChildVM - 它会显示在列表框中,但不会显示为 FileName。相反,我只是得到 FullFileName。
按理说我错过了触发绑定的事件,但我不完全确定我应该首先以这种方式绑定。
这是功能代码。请注意,出于这个问题的目的,我已经简化了它。您可以忽略命名约定等。
这是用户控件。它是一个包含 FileInfo 对象的列表框,我想为其设置 DisplayMemberName 为 FileInfo.FileName 值。
<UserControl x:Class="CatalogInterface.ctlDirFilesListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CatalogInterface"
xmlns:vm="clr-namespace:CatalogInterface.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="MainControlGrid">
<ListBox x:Name="FileListBox"
DisplayMemberPath="{Binding ElementName=Files, Path=Files.FileName}"
<!-- Also tried DisplayMemberPath="FileName" -->
ItemsSource="{Binding Files}"
SelectedItem="{Binding Path=SelectedFiles}"
SelectionChanged="ListBoxItem_SelectionChanged"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#FFFFFF"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="3"
BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/>
<EventSetter Event="KeyDown" Handler="ListBoxItem_KeyDown"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</UserControl>
这是我的包含 UserControl 的 MainWindo 视图:
<Window x:Name="FCTWindow" x:Class="CatalogInterface.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CatalogInterface"
xmlns:vm="clr-namespace:CatalogInterface.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="532">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<!--#region Body Left Side Grid-->
<Grid x:Name="BodyGridLeft" Grid.Row="0" Grid.Column="0">
<UserControl Content="{Binding DirFilesViewModel}">
<UserControl.ContentTemplate>
<DataTemplate>
<local:ctlDirFilesListBox />
</DataTemplate>
</UserControl.ContentTemplate>
</UserControl>
</Grid>
<!--#endregion Body Left Side-->
</Window>
这是 UserControl 的 VM(用户控件实际上是我为此问题简化的更复杂的子视图的一部分)在 VM 中,当调用 OnPublishDirFiles() 时更新列表框:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
namespace CatalogInterface.ViewModels
{
public class DirFilesViewModel : ViewModelBase<DirFilesModel>
{
private object _selectedFiles;
private Messenger _messenger;
public object SelectedFiles
{
get { return _selectedFiles; }
set {
SetProperty<object>(ref _selectedFiles, value);
_messenger.SendMessage(this, "DirFilesListBox_SelectedDocumentChanged", _selectedFiles);
}
}
public ObservableCollection<FileInfo> Files { get; set; }
private DirFilesModel _model;
public DirFilesViewModel()
{
_model = new DirFilesModel();
Files = new ObservableCollection<FileInfo>();
this.OnPublishDirFiles(this, new MessageEventArgs("s", "o"));
_messenger = Messenger.Set_Messenger();
_messenger.Register(OnPublishDirFiles, "PublishDirFiles");
}
protected virtual void OnPublishDirFiles(object source, MessageEventArgs e)
{
PublishDirFiles();
}
private void PublishDirFiles()
{
if (Files == null) { } //raise NullArgumentException
Files.Clear();
foreach (FileInfo f in _model.Files) Files.Add(f);
OnPropertyChanged("Files.FileName");
}
}
}
不就是DisplayMemberPath="Name"
吗?我没有看到实际的 "FileName" 属性。有 Name
和 FullName
。