【问题标题】:MVVM Understanding IssuesMVVM 理解问题
【发布时间】:2015-11-21 16:22:00
【问题描述】:

我对 mvvm 的问题列表,您不需要自己回答,我们始终感谢能进一步帮助我的链接:

  1. 如果我有一个 Mainpage.xaml 文件并且我正在使用 viewmodelclass,那么 Mainpage.xaml.cs 文件中应该包含哪些代码?没有?

  2. 那段代码是否应该在 Mainpage.xaml.cs 文件中:

    Viewmodel base = new Viewmodel();

  3. 如果我实现 ICommands,我如何访问 Mainpage.xaml 上的 textbox.text?

  4. ICommands 完全取代了 Button.Click 事件?不是吗?

【问题讨论】:

  • 我不知道是谁在回答这个问题,但我认为@Matthias 从某人的角度提出了非常有效的问题,他想采用 MVVM 但没有以前的经验。
  • 我最近写了一篇关于 MVVM 最佳实践的文章,查看blog.rsuter.com/…

标签: c# wpf xaml mvvm


【解决方案1】:
  1. 如果我有一个 Mainpage.xaml 文件并且我正在使用一个 viewmodelclass 代码应该在 Mainpage.xaml.cs 文件中吗?什么都没有?

您需要了解什么是视图以及视图模型的职责。 Codebehind 是 view 的一部分,所以只有被 view 的职责覆盖的代码才应该在 code behind 中。

有时在 xaml 中很难将数据绑定到视图模型(例如 PasswordBox)然后您可以使用代码隐藏来获取密码或捕获更改并在视图模型中设置属性。您不应该在代码隐藏中针对服务器验证密码。

有时很难在 xaml 中定义动画。随意在 C# 中创建或触发它们(但在这种情况下,您将无法在 Expression Blend 中进行编辑)

可以在代码隐藏中使用 Loaded / Unloaded 之类的偶数,例如我使用它们在我的视图模型中调用激活/停用方法。

这是代码隐藏示例,不违反视图和视图模型的关注点分离:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Closing += MainWindow_Closing;
    }

    MainWindowViewModel ViewModel
    {
        get { return (MainWindowViewModel)DataContext; }
    }

    void MainWindow_Closing(object sender, CancelEventArgs e)
    {
        var canExit = ViewModel.ShowConfirmExitDlg();
        if (!canExit) e.Cancel = true;
    }
}

换句话说,有时您必须使用代码隐藏。有人说你永远不应该使用它,而是要务实并在它对你有帮助的时候使用它。

  1. 那段代码是否应该在 Mainpage.xaml.cs 文件中:Viewmodel base = new Viewmodel();

是的,没关系。但是,您应该在 xaml 中使用 d:DataContext 以便让 Visual Studio 设计器知道您正在使用什么数据上下文,以便它可以为您提供智能感知和设计时支持。有很多方法可以设置实例视图模型并将其设置为数据上下文。任你选择。

  1. 如果我实现 ICommands,我如何访问 Mainpage.xaml 上的 textbox.text?

在视图模型中创建字符串属性并将 textbox.text 数据绑定到它。使用 DelegateCommand,您可以在其中传递有权访问该属性的方法:

public class MainWindowViewModel 
{
    public MainWindowViewModel()
    {
        LoginCommand = new DelegateCommand(Login);
    }

    public DelegateCommand LoginCommand { get; private set; }

    public string Username { get; set; }
    public string Password { get; set; }

    private void Login()
    {
        if (Username == "user" && Password == "user")
        {

        }
    }
}

仅供参考,还有另一种将参数传递给命令的方法:检查命令参数功能[link]

  1. ICommands 完全取代了 Button.Click 事件?不是吗?

几乎。与第一个问题的答案相同的规则也适用于此。

【讨论】:

  • 所有非常好的观点,我唯一要质疑的是代码隐藏。具体来说,它不违反SOC的声明。代码隐藏中的任何内容都不能进行单元测试,并且调用对话框的创建是逻辑,因此不应该出现在视图中(无耻的插件:请参阅我在 MVVM dialog boxes 上的文章以讨论围绕此的问题) .如果您实际上不需要单元测试,您当然可以摆脱它,但从技术上讲,它确实打破了这种模式。
  • 我已经将关闭事件“绑定”到视图模型中的方法。我在代码隐藏中做到了。这与将文本框绑定到 viewmodel 属性相同。我可以在 xaml 中使用一些 EventTriggers 广告 CallMethod 操作来做到这一点,但它有什么区别?你会怎么做?
  • @MarkFeldman:你能检查一下this的问题吗?
【解决方案2】:
  1. 理想情况下,是的。但在大多数情况下,很难遵循
  2. 并非在所有情况下。如果你的 ViewModel 的构造函数不接受参数,你可以用 xaml 来写:

    <Window.Resources>
        <local:ViewModel x:Key="viewModel" /> <!-- this row will automatically create instance of ViewModel class-->
    </Window.Resources>
    

如果视图模型类接受参数,那么是的,你必须写:

ViewModel base = new Viewmodel(yourArgs);
this.DataContext = base;

在代码隐藏中。

  1. 如果你想跟随MVVM,将TextBox的Text属性绑定到Viewmodel属性:

    <TextBox Text="{Binding MyText}" />
    

在 ViewModel 中:

private string _myText;
public string MyText
{
    get { return _myText; }
    set 
    {
        if (_myText != value)
        {
            _myText = value;
            // NotifyPropertyChanged("MyText"); if needed
        }
    }
}

然后您可以使用 RelayCommand 或 DelegateCommand (google it) 在 ViewModel 中对 TextBox 的文本进行操作。

  1. 是的。 Command 还允许将参数传递给 ICommand(例如,当您将使用 RelayCommand 时)

希望,它会有所帮助。

【讨论】:

    【解决方案3】:
    1. 我尽量将后面的代码保持在最低限度。我仍然倾向于将表单关闭逻辑放在那里。

    2. 许多人使用依赖注入从 WPF 表单外部执行此操作。

    3. 您可以使用数据绑定到视图模型上的 textbox.text 属性(使用 INotifyPropertyChanged)并在 ViewModel 中修改它。表单将自动更新以反映任何更改。

    4. 是的,它将代码从表单抽象到视图模型。

    YouTube 上有一些很棒的视频详细解释了这些概念。

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      我认为您的问题表明您还没有真正开始深入研究带有 MVVM 的 WPF。

      大多数“入门”教程都会解决您的问题。 我最喜欢的教程是 Josh Smith 的 WPF Apps With The Model-View-ViewModel Design Pattern

      那个人会给你一个所有问题的有效答案。不要忘记下载文章的代码示例以获得完整的演示应用程序! :-)

      【讨论】:

        【解决方案5】:

        这个问题可能会因为不够具体而被删除,但不管怎样……

        如果我有一个 Mainpage.xaml 文件并且我正在使用一个 viewmodelclass 代码应该在 Mainpage.xaml.cs 文件中吗?什么都没有?

        不只是 MainPage,任何其他窗口或控件类也是如此(除了一些我不会在这里介绍的例外情况)。您应该能够在不创建单个视图的情况下创建、运行和单元测试整个应用程序。视图模型是您的应用程序,当您以需要用户交互的方式(即非单元测试)运行应用程序时,视图只是呈现给用户的松散绑定的图形 UI 表示。

        Viewmodel base = new Viewmodel();

        这是一个有点复杂的话题,但高层次的答案是“使用依赖注入框架”。通过 NuGet 将 MVVM Lite 添加到您的项目中会自动为您设置一个非常简单的框架,否则 Google 就是您的朋友。

        如果我实现 ICommands,我如何访问例如 textbox.text 在 Mainpage.xaml 上?

        您使用 getter 和 setter 将字符串属性添加到视图模型,并将文本框的 Text 属性绑定到该属性。

        ICommands 完全取代了 Button.Click 事件?不是吗?

        一般来说,是的。使用 WPF 的“正确”方法是将命令绑定到命令处理程序。添加事件处理程序之类的东西的原因与添加属性 getter 和 setter 的原因相同,即帮助简化从旧 WinForms 做事方式的过渡。仅仅因为框架支持它并不意味着它是正确的处理方式。

        【讨论】:

        • 我或多或少同意你在这里提出的所有观点。我刚刚用更多细节和代码示例扩展了您的答案。
        猜你喜欢
        • 2010-12-15
        • 2011-07-04
        • 1970-01-01
        • 1970-01-01
        • 2011-10-11
        • 2011-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多