【问题标题】:How to share a binding value between multiple views?如何在多个视图之间共享一个绑定值?
【发布时间】:2019-12-10 11:28:44
【问题描述】:

我是 WPF 和 MVVM 的新手(来自 WinForms 和 Events),所以请多多包涵!

我试图弄清楚如何在多个视图之间使用相同的INotifyPropertyChanged 值绑定。我正在使用 MVVM Light。我有从 ViewModelBase 继承的 ViewModels 支持我的视图(没有后面的代码)。我不知道如何解释这个问题,但我认为一个例子可以清楚地说明我所追求的。

我有一个主窗口。它有一个标准的TabControl。在登录 TabItem 我有一个自定义登录控件。在TabControl 下方,我有一个自定义状态栏控件。期望的行为是,当用户登录时,状态栏会更新他们的登录状态和名称,并且主窗口上的其他 TabItems 会启用(未登录时应该禁用它们)。

总结一下,我有:

  • MainWindow(视图)与 MainWindowViewModel
  • 使用 LoginViewModel 登录(查看)(在 MainWindow 的 TabControl 中)
  • StatusBar(视图)和 StatusBarViewModel(位于 MainWindow 底部)

这是我的StatusBarViewModel 的样子:

public class StatusBarViewModel : ViewModelBase, IStatusBarViewModel
{
    private bool _isLoggedIn;
    public bool IsLoggedIn
    {
        get { return _isLoggedIn; }
        set { Set(ref _isLoggedIn, value); RaisePropertyChanged(); }
    }
    // other properties follow
}

我通过构造函数注入(使用 Ninject)将IStatusBarViewModel 的(单例)具体实例注入 LoginViewModel:

public class LoginViewModel : ViewModelBase
{
    private IStatusBarViewModel _statusBar;

    public LoginViewModel(IStatusBarViewModel statusBar)
    {
        _statusBar = statusBar;
    }
}

我对 MainWindowViewModel 做同样的事情:

public class MainWindowViewModel : ViewModelBase
{
    private IStatusBarViewModel _statusBar;

    public bool IsLoggedIn => _statusBar.IsLoggedIn;

    public MainWindowViewModel(IStatusBarViewModel statusBar)
    {
        _statusBar = statusBar;
    }
}

注意:我认为这是我的问题所在......不确定 MVVM Light 是否将其解释为可绑定属性并应用正确的更改通知。如果我添加一个 setter(我在这里不需要),那将不起作用,因为 A property or indexer may not be passed as an out or ref parameter。所以我不清楚当我这样做时发生了什么。

回到正轨,所以当登录成功时,我可以像这样从LoginViewModel 更新IsLoggedIn 属性:

_statusBar.IsLoggedIn = true;

我在我的 MainWindow XAML 中设置绑定,如下所示:

<TabItem Header="Event" IsEnabled="{Binding IsLoggedIn}">
    <views:Events/>
</TabItem>

第一次加载视图时绑定正常工作,但随后对属性的更改不会触发IsEnabled 的更改。但是,状态栏(视图)会相应更新。

我曾考虑将 StatusBarViewModel 和 MainWindowViewModel 的引用注入到我的 LoginViewModel 中(然后必须在登录后设置两个属性),但这让我认为我没有正确处理这个问题,因为我'正在创建依赖项。

所以基本上问题是:

  • 按照 MVVM 模式,我的方法是否正确?
  • 我是否走在正确的轨道上,只需要稍微修改一下代码吗?
  • 如果不是,处理这种情况的(或一种)标准模式是什么?

【问题讨论】:

    标签: c# wpf mvvm data-binding mvvm-light


    【解决方案1】:

    你的猜测是正确的。问题出在这里:

    public bool IsLoggedIn => _statusBar.IsLoggedIn;
    

    ... 因为它不会生成更改通知。您可以做的只是通过公共属性公开 IStatusBarViewModel,然后直接绑定到它自己的 IsLoggedIn 属性。

    在 ViewModel 中:

    public class MainWindowViewModel : ViewModelBase
    {
        private IStatusBarViewModel _statusBar;
        public IStatusBarViewModel StatusBar => _statusBar;
        public MainWindowViewModel(IStatusBarViewModel statusBar)
        {
            _statusBar = statusBar;
        }
    }
    

    在视图中:

    <TabItem Header="Event" IsEnabled="{Binding StatusBar.IsLoggedIn}">
        <views:Events/>
    </TabItem>
    

    【讨论】:

    • 太棒了。所以这里的要点是更改通知只会在 ViewModelBase 对象本身上冒泡,而不是在属性上?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 2023-02-11
    相关资源
    最近更新 更多