【问题标题】:How to Access a property which is assigend in codebehind in the View Model in WPF MVVM?如何访问在 WPF MVVM 的 Viewmodel 后面的代码中分配的属性?
【发布时间】:2020-01-19 17:16:39
【问题描述】:

我目前正在使用 WPF MVVM 模式实现应用程序。在那里我遇到了一个问题,我在代码隐藏(比如说 Author.xaml.cs)中,在中介方法中分配了一些属性(IsClickedYes 为 true),然后当中介返回到特定的视图模型(AuthorViewModel.cs)时,我需要从 AuthhorViewModel.cs 访问 Author.xaml.cs 中的 IsClickedYes 属性。我怎样才能做到这一点?

作者.cs

public class Author
{
    private bool _isClickedYes;

    public bool IsClickedYes
    {
     get { return _isClickedYes; }
     set { _isClickedYes= value; }
    }
    public Author()
    {
    Mediator.Register("SetClickedYesProperty",SetClickedYes);
    }

    private void SetClickedYes(object parameter)
    {
     //Show a Confirm Message Dialog here then if user clicked yes set IsClickedYes property to true

    _isClickedYes=true;
    }
}

AuthorViewModel.cs

public class AuthorViewModel
{
//this will call the SetClickedYes method in Author.xaml.cs
Mediator.NotifyCollegue("SetClickedYesProperty",null);

//then here I need to access the IsClickedYes Property value of Author.xaml.cs 
if IsClickedYes == true , then do a certain operation otherwise do nothing.


}

如果我尝试在 AuthorViwModel 中创建一个属性并在代码隐藏中设置该属性,则当它从中介返回时,它变为空。这就是为什么我在代码隐藏中创建属性并在那里分配值,并尝试从视图模型访问它。 我该如何实现这一点,还有其他方法可以实现吗?如果还有其他更好的方法可以实现这一点,请任何人指导我?任何建议将不胜感激!

【问题讨论】:

  • 不知道为什么不绑定?将 IsClickedYes 属性移动到 ViewModel 之后,然后使用特殊控件绑定,您将获得所需的一切。

标签: c# wpf mvvm mediator


【解决方案1】:

我建议 IsClickedYes 属性应该是您的视图模型的一部分。如果您将视图模型传递给视图的构造函数,那么一切都会变得非常简单。您可以在代码中设置值(仍然),并且您的视图模型将始终处理该值。视图中的控件(可能是复选框,但可能是另一种切换?)然后可以将其值绑定(两种方式)到视图模型属性。对于这个简单的案例,根本不需要使用中介。

【讨论】:

  • IsClicked 是 UI 逻辑的一部分,不属于 MVVM 场景中的视图模型。视图知道其属性的状态,并且可以通过调用视图模型上的命令或方法来进行相应的操作。视图模型只知道模型的状态。 IsClicked 这个名字可能是个坏名字,或者它只是反映了按钮的状态。
  • @BionicCode 我猜我的阅读与你的不同。我认为这是一个带有直接与视图模型相关联的复选框的视图。单击复选框本质上是将布尔值传播回数据模型的一种方式。甚至排序和过滤也由 VM 处理(使用 collectionview 或本地方法)。
  • 是的,有点不知道。这就是为什么我说他可能用了一个坏名字。如果 IsClicked 反映了启用的过滤器,则应将其称为 IsFilterEnabled。在这种情况下,你是对的。如果它是用于确定按钮状态的视图相关属性,则名称可以,但它不属于视图模型。我就是这么说的。我们目前不知道任何细节,应该清楚区别,因为他强调他正在使用 MVVM。
【解决方案2】:

MVVM 明智的做法是将属性IsClicked 放入视图模型是错误的。它是查看相关数据,仅查看相关。你应该尽量避免这种情况,它几乎是可以避免的。

当涉及到视图触发视图模型操作时,您应该想到命令模式。

但如果IsClicked 反映了视图模型状态,例如IsDataFilterEnabled,那么您可以按照其他人的建议使用数据绑定。但在这种情况下,您为 Author 属性选择了一个非常糟糕的名称。名称 IsClicked 和按钮的状态是关联的。

Author.xaml.cs

public partial class Author : Window
{
  private bool _isClicked;
  public bool IsClicked
  {
    get { return _isClicked; }
    set { _isClickedYes= value; }
  }

  public Author()
  {
    Mediator.Register("EnableIsClickedProperty", EnableIsClicked);
  }

  private void EnableIsClicked(object parameter)
  {
    _isClicked = dialogResult;

    // Assuming that AuthorViewModel is the DataContext of the Author view
    var viewModel = this.DataContext as AuthorViewModel;
    if (_isClicked && viewModel.DoCertainOperationCommand.CanExecute())
    {
      viewModel.DoCertainOperationCommand.Execute();
    }
  }
}

AuthorViewModel.cs

public class AuthorViewModel
{
  public ICommand DoCertainOperationCommand => new RelayCommand(DoCertainOperation, CanExecuteDoCertainOperation);

  private void DoSomething()
  {
    //this will call the EnableIsClicked method in Author.xaml.cs
    Mediator.NotifyCollegue("EnableIsClickedProperty", null);
  }

  private void DoCertainOperation(object param)
  {
    // As this method is only invoked by the view when Author.IsClicked == true,
    // the view model doesn't need to care about the view's property states.
    // IsClicked is UI logic and belongs solely to the view.
  }

  private bool CanExecuteDoCertainOperation => true;
}

为简洁起见,我没有在此处发布RelayCommand 的代码。您要么已经有自己的实现,要么会在 web 中找到几十个。

或者直接调用视图模型的 API(从代码隐藏)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 2013-07-05
    • 2020-10-15
    • 1970-01-01
    相关资源
    最近更新 更多