绑定到可观察属性,但显示不可观察的子属性

Posted

技术标签:

【中文标题】绑定到可观察属性,但显示不可观察的子属性【英文标题】:Bind to observable property, but show a non-observable sub-property 【发布时间】:2021-11-22 12:58:05 【问题描述】:

我正在尝试编写一个基于 MVVM 和 WinUI3 的应用程序。我有一个 ViewModel 属性 SelectedFolder,它是可观察的(使用 MVVM Toolkit)。这是文件夹类型,它是一个普通的旧类。像这样的:

public class ViewModel: ObservableRecipient 
    private Folder selectedFolder;
    public FolderModel SelectedFolder
    
        get => selectedFolder;
        set => SetProperty(ref selectedFolder, value, true);
    

public class FolderModel 
    public string Name  get; set; 

现在在我的 XAML 中,我想绑定 ViewModel.SelectedFolder,并对它的更改做出反应,但我想显示 ViewModel.SelectedFolder.Name。所以我正在寻找这样的东西(不存在):

<TextBlock Text="Binding ViewModel.SelectedFolder,Property=Name" />

我怎样才能做到这一点?我想到的事情:

让一切都可以观察到。这行得通,但我试图避免这种情况,以便分离我的模型和我的视图模型。原因是我的真实模型比这个例子复杂得多,我试图让它接近对我的“业务逻辑”有意义的东西,并使我的视图模型满足我的视图需求。 为我的 ViewModel 的需要创建另一个具有可观察属性的“文件夹”类。我不想这样做,因为它会重复很多代码。 向我的 ViewModel 添加一个可观察的字符串属性:“SelectedFolderName”。 滥用转换器,写一个GetNamePropertyConverter,看起来真的很傻。

【问题讨论】:

让一个模型可观察,你希望它的变化是可观察的,这似乎是这里最直接的设计选择。您不需要让每个属性都可观察。 是的,但是文件夹的属性不会改变,它基本上是不可变的。我想换掉整个对象。 因为您的 ViewModel 是可观察的,所以当 SelectedFolder 更改时,如果您将其绑定为 Binding ViewModel.SelectedFolder.Name,则新的 Name 属性值将显示在 UI 中。如果您只想在 SelectedFolder 设置为新值时更改 Name 的数据绑定值,则无需执行任何其他操作。 【参考方案1】:

像这样绑定到模型的Name 属性应该可以工作,因为您正在设置SelectedFolder 并为其引发PropertyChanged 事件:

<TextBlock Text="Binding ViewModel.SelectedFolder.Name " />

一般来说,您不应直接绑定到包含“业务逻辑”的模型对象。相反,您应该将模型属性包装在视图模型中并绑定到包装器属性:

public class ViewModel : ObservableRecipient

    private Folder selectedFolder;
    public FolderModel SelectedFolder
    
        get => selectedFolder;
        set
        
            SetProperty(ref selectedFolder, value, true);
            OnPropertyChanged(nameof(FolderName));
        
    

    public string FolderName => selectedFolder?.Name;

XAML:

<TextBlock Text="Binding FolderName" />

【讨论】:

是的,你完全正确。我创建了一个新项目,它可以工作。我想我可能在 WinUI3 1.0 Preview 中遇到了一些错误。我也遇到过与绑定相关的崩溃 (github.com/microsoft/microsoft-ui-xaml/issues/3680)。当然也有可能我只是在某个地方出现了一个愚蠢的错字......

以上是关于绑定到可观察属性,但显示不可观察的子属性的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 ListView 数据绑定到可观察集合不能正确显示

Ionic 4 Angular模板与异步管道绑定到可观察

knockoutjs 可观察对象绑定的可观察数组

刷新 WPF Datagrid 未绑定到可观察集合?

将多个输入绑定到可观察数组中的同一变量(Knockout.JS)

Knockoutjs:一些可观察的绑定但在 Safari 中不可见