2

我正在试验 MVVM,但我无法完全理解它。

我有一个视图(windows),它有几个重复的控件。

假设我有 4 个文本框 - 按钮对。他们的行为应该是相同的,在按下按钮配对文本框后显示“Hello World!”

我尝试了几个我能想到的选项:

  1. 一个 ViewModel,绑定到文本框的 4 个字符串属性,1 个命令
    • 当我将每个按钮绑定到同一个命令时,我不知道需要设置哪个属性。
    • 将枚举传递给 CommandParameter 感觉很尴尬。
  2. 一个 ViewModel 和 UserControl 承载一个文本框和一个重复 4 次的按钮。
    • 现在我需要公开所有属性,如命令、命令参数、文本等。看起来工作量很大。
    • 还是不能说点击后需要更新哪个属性。
  3. 每个 UserControl 都有一个 ViewModel
    • 这解决了按钮单击和设置属性,但现在我不知道如何将文本从嵌套的 ViewModel 提取到窗口 ViewModel。

还有其他方法吗?我怀疑 DataTemplates 可能有用,但我不确定如何使用。

4

3 回答 3

2

你所描述的是一个如此抽象和人为的想法,它不能保证 MVVM。您说的是TextBoxes 和Buttons,它们都是“视图”,而不是 MVVM 的思维方式。你几乎总是从模型开始。

不过,这里没有“模型”本身;您的规范实际上是TextBoxButton单击时设置 a 的值。看似随机的“4”项列表(不知从何而来)和看似无用的TextBox东西毫无意义。

抛开这一点,假设您有一组 4 个业务实体,每个业务实体上都有一个用户可编辑的字段,以及用户可以触发的操作,您可以这样做:

  • 创建一个 ViewModel 类来表示一个项目 - 例如MyItemModel
  • 创建一个 ViewModel 类来表示一组项目(可能它只会返回第一个集合) - 例如AllMyItemsListModel

然后对于视图:

  • 创建一个ItemsControl,ItemsSource绑定到第二个 ViewModel 类的“集合”实例
  • 对于每个ItemTemplate,有一个模板或UserControl每个项目
  • 在模板或UserControl中,将 的 Text 属性绑定TextBox到第一个类的适当属性
  • Button将' 的Command属性绑定到第一个返回ICommand-的类上的属性RelayCommand,例如

我不知道您所说的“将文本从嵌套的 ViewModel 提取到窗口 ViewModel”是什么意思 - 这是什么意思,您为什么要这样做?

希望有帮助。

于 2010-07-23T19:35:34.523 回答
1

第 3 号。除了只有一个带有 viewmodel 的 UserControl,然后是 Main 页面,上面有该 UserControl 的多个实例。如果主窗口需要来自 UserControl 的信息,您可以通过事件传递它或使用MVVM Light之类的东西,它是信使类。

于 2010-07-23T17:27:17.173 回答
1

无需为具有如此简单行为的可重用控件创建单独的 ViewModel。只需向简单的 UserControl 添加一些 DependencyProperties 和事件处理程序,您就可以重用逻辑并仅设置每个实例上实际不同的属性。对于 UserControl XAML,您只需将 TextBox 连接到 DependencyProperty 并将 Button 连接到 Click 处理程序。

<DockPanel>
    <Button Content="Reset" Click="Button_Click"/>
    <TextBox Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Text}"/>
</DockPanel>

UserControl 的代码只需要定义可以外部绑定的属性和重置文本的处理程序。

public partial class ResetTextBox : UserControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(ResetTextBox),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty ResetTextProperty = DependencyProperty.Register(
        "ResetText",
        typeof(string),
        typeof(ResetTextBox),
        new UIPropertyMetadata(String.Empty));

    public string ResetText
    {
        get { return (string)GetValue(ResetTextProperty); }
        set { SetValue(ResetTextProperty, value); }
    }

    public ResetTextBox()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Text = ResetText;
    }
}

然后要使用控件,您只需绑定到 ViewModel 字符串属性并设置应在重置时应用的默认文本,可以在此处硬编码,也可以绑定到其他 VM 属性。

<StackPanel>
    <local:ResetTextBox ResetText="One" Text="{Binding Name1}"/>
    <local:ResetTextBox ResetText="Two" Text="{Binding Name2}"/>
    <local:ResetTextBox ResetText="Three" Text="{Binding Name3}"/>
</StackPanel>
于 2010-07-23T22:53:24.543 回答