【问题标题】:Get PropertyChanged notification from one ViewModel to another从一个 ViewModel 到另一个 ViewModel 获取 PropertyChanged 通知
【发布时间】:2020-01-07 21:35:05
【问题描述】:

我正在开发我的第一个 WPF 项目。 我的 UI 需要更具交互性。我有 2 个 ViewModel。 MainWindowViewModel 和 WorldViewModel。

MainWindow xaml 简化代码:

<Window>
    [...]
    <Window.DataContext>
        <vm:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <!--Worlds combobox-->
        <ComboBox Margin="2 0 0 0" MinWidth="100" IsEnabled="{Binding IsWorldsComboEnabled}"
        ItemsSource="{Binding WorldViewModel.Worlds}" SelectedValue="{Binding WorldViewModel.CurrentWorld}"
        DisplayMemberPath="Name"/>
    </Grid>
</Window>

MainWindowViewModel.cs 代码:

public class MainWindowViewModel : BaseViewModel
{
    public WorldViewModel WorldViewModel { get; set; }

    public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null;

    /// <summary>
    /// Default constructor
    /// </summary>
    public MainWindowViewModel()
    {
        WorldViewModel = WorldViewModel.Instance;
    }
}

WorldViewModel.cs 代码:

public class WorldViewModel : BaseViewModel
{
    public ObservableCollection<World> Worlds { get; set; }

    public World CurrentWorld { get; set; }

    public static WorldViewModel Instance { get; set; }

    // Called on startup
    public static void Initialize()
    {
        Instance = new WorldViewModel();
    }

    /// <summary>
    /// Default constructor
    /// </summary>
    public WorldViewModel()
    {

    }
}

ViewModel 有点大,但这是最少需要的代码。 BaseViewModel 是一个类,它通过PropertyChanged.Fody NuGet 包提供 NotifyPropertyChanged 接口。

Worlds ObservableCollection 为空时,我的ComboBox 必须被禁用。当IsWorldsComboEnabled位于WorldViewModel时效果很好,但我觉得这不是一个办法。多个视图将取决于WorldViewModel,但它们不需要IsWorldsComboEnabled 属性。所以它的位置在MainWindowViewModel

WorldViewModel 中的属性发生变化时,有什么方法可以通知MainWindowViewModel

【问题讨论】:

  • IsWorldsComboEnabled 位于 WorldViewModel 时效果很好,但我觉得这不是办法。 所以绑定WorldViewModel.IsWorldsComboEnabled 不是办法但你觉得绑定WorldViewModel.Worlds 是一种方式...这很奇怪...每个ViewModel 都应该有自己的View ...
  • MainWindowViewModel 具有视图逻辑。 WorldViewModel 将不包含任何视图逻辑,因为多个视图可以依赖此 ViewModel。我绑定MainWindowViewModel.IsWorldsComboEnabled 是正确的。你可能误解了我的意思。 IsWorldsComboEnabled 依赖于 WorldViewModel.Worlds,但它的位置在 MainWindowViewModel
  • 你又一次误解了 MVVM,每个 ViewModel 都应该有它的 View(除非是抽象的并且会被扩展)
  • IsWorldsComboEnabled 依赖于 WorldViewModel.Worlds,但它的位置在 MainWindowViewModel 然后 MainWindowViewModel 也是 Worlds 应该在的位置...将 Worlds 和其他东西移到 MainViewModel跨度>
  • 如果多个视图需要对同一个对象集合实例进行操作怎么办。那么在哪里存储数据呢?

标签: c# wpf mvvm inotifypropertychanged


【解决方案1】:

下面这行代码的问题是IsWorldsComboEnabled的setter即使WorldViewModel.Worlds改变也不会被执行,因此你的PropertyChangedEventHandler不会被调用。

public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null

你可以改成public bool IsWorldsComboEnabled { get; set; } 并计算以下表达式

IsWorldsComboEnabled = WorldViewModel.Worlds != null;

每当您更改属性 WorldViewModel.Worlds 时。

在您的情况下,如果属性是 ObservableCollection,您可以注册到 CollectionChanged 事件

WorldViewModel.Worlds.CollectionChanged += MyCollectionChangedMethod;

并在那里计算表达式

private void MyCollectionChangedMethod(object sender, NotifyCollectionChangedEventArgs e)
{
  IsWorldsComboEnabled = WorldViewModel.Worlds != null;
}

【讨论】:

  • 谢谢。这正是我需要的!太感谢了! ☺
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
相关资源
最近更新 更多