TextBox.TextChanged & ICommandSource

10
我正在遵循M-V-VM模式来设计我的WPF UI。我想将一个命令与一个TextBox的TextChanged事件连接到ViewModel类中的一个命令。我能想到的唯一完成此任务的方法是继承TextBox控件并实现ICommandSource接口。然后我可以指示从TextChanged事件触发命令。这似乎对于看起来如此简单的事情来说太麻烦了。
是否有比子类化TextBox并实现ICommandSource更简单的方法将TextChanged事件连接到我的ViewModel类?
3个回答

18

首先,您肯定考虑过在双向数据绑定到视图模型时使用PropertyChanged的UpdateSourceTrigger吧?这样,每当文本更改时,您绑定到的属性设置器将被调用。

如果这还不够,那么我会使用附加行为来解决这个问题。在Julian Dominguez的博客上,您可以找到一篇关于如何在Silverlight中执行非常类似操作的文章,该方法应该很容易适用于WPF。

基本上,在一个静态类(称为TextBoxBehaviours)中,您定义了一个名为TextChangedCommand的附加属性,类型为ICommand。挂钩一个OnPropertyChanged处理程序来处理该属性,并在处理程序内部检查该属性是否正在设置在一个TextBox上;如果是,就添加一个处理程序到TextBox的TextChanged事件,该处理程序将调用属性中指定的命令。

然后,假设您的视图模型已经分配给了您的View的DataContext,您可以像这样使用它:

<TextBox
  x:Name="MyTextBox"
  TextBoxBehaviours.TextChangedCommand="{Binding ViewModelTextChangedCommand}" />

1
谢谢Sam - 有时候我会忽略简单的选项;在这种情况下,就是将文本框绑定到ViewModel中的字符串属性。 - Brad Leach
我认为在属性的setter中添加逻辑是行不通的。WPF XAML处理器直接使用依赖属性而不是通过属性包装器进行操作。这意味着当UI更新时,setter将永远不会被调用。(来源:http://msdn.microsoft.com/en-us/library/bb613563.aspx) - Greg
2
Greg,我指的是 ViewModel 中绑定了依赖属性的属性的 Setter,而不是依赖属性本身的 Setter。 - Samuel Jack

8

使用事件绑定和命令方法可能不是正确的选择。

这个命令到底会做什么?

您可能想考虑使用数据绑定到VM中的字符串字段。这样,您可以从那里调用命令或函数,而不必让UI关心任何事情。

<TextBox Text="{Binding WorldName}"/>
....
public string WorldName
{
    get
    {
        return WorldData.Name;
    }
    set
    {
        WorldData.Name = value;
        OnPropertyChanged("WorldName");
        // CallYourCustomFunctionHere();
    }
}

谢谢Nidonocu。你的回答也很完美,但我标记了Sam的回答作为答案,因为他比你稍微早一些回答。不过还是非常感谢! - Brad Leach

2

你不能仅仅处理TextChanged事件并从那里执行命令吗?

private void _textBox_TextChanged(object sender, EventArgs e)
{
    MyCommand.Execute(null);
}

就像你所说的那样,另一种方法是创建一个TextBox作为命令源,但这似乎有些过度设计,除非你计划在许多地方共享和利用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接