我有一个用户控件,说一个我想在其他几个控件中重用的键盘。键盘响应 INotifyPropertyChanged 但我想捕获父控件中的更改以更新其中的文本框。
我试图从父视图模型访问控件,但这不是使用 MVVM 执行此操作的正确方法。
任何想法表示赞赏。
我认为你有点混淆了想法。
MVVM 方式是有两个视图模型和两个视图。
MasterControlViewModel
&MasterControlView
KeypadControlViewModel
&KeypadControlView
MasterControlViewModel
将订阅在KeypadControlViewModel
.
但是,您似乎推断这KeypadControl
只是一个标准控件,没有自己的视图模型。考虑到它与视图的密切关系(它提供键盘输入,插入取决于光标所在的位置等),这将是有意义的。如果是这种情况,拥有一个“目标”依赖属性可能更合适,KeypadControl
该属性可以绑定到MasterControlView
. 当一个键被点击时,它KeypadControl
只是更新目标控件,或者,可能更好的是,它可以触发键盘 RoutedEvents,它会像真正的键盘事件一样沿着可视化树向上移动,从而不需要目标属性。
这样,您的所有输入内容都会在视图中处理,并且MasterControlViewModel
唯一关心的是字符串已更改的事实。
我想说,如果你想做 MVVM 风格,那么键盘控件应该公开一个 ICommand 属性,命令本身由父级提供,并在单击某个键时执行该命令。
该命令将获取在命令参数中单击的键。
实际的命令实现将在父控件中(您可以为此使用RelayCommand 模式),然后可以更新其 TextBox。
键盘类应包括如下内容:
class Keypad : UserControl
{
...
public DependencyProperty OnKeypadKeyClickedCommandProperty = ... ;
...
void OnZeroButtonClicked(object sender, RoutedEventArgs e)
{
OnKeypadKeyClickedCommand.Execute(this, new SomeKeyIdentifier('0'));
}
...
}
XAML 应包括如下内容:
<local:Keypad OnKeypadKeyClickedCommand="{Binding HandleKeypadKeyClickCommand, ElementName=parentControlName}" />
父控件中的实现应该是这样的:
class ParentControl : ...
{
DependencyProperty HandleKeypadKeyClickCommand = ...;
void Init()
{
HandleKeypadKeyClickCommand = new RelayCommand(new Action<SomeKeyIdentifier>(DoKeyPress));
}
...
void DoKeyPress(SomeKeyIdentifier key)
{
_Textbox.Text += key.Char;
}
...
}