65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight:SetTextBoxFocusUsingMVVM

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (12投票s)

2010 年 9 月 19 日

CPOL

3分钟阅读

viewsIcon

43760

downloadIcon

680

如何在验证时使用 MVVM 模式在文本框中设置焦点。

引言

MVVM 是微软的一种架构模式。View 类不知道模型是否存在,但是 viewmodel 和模型不知道 view。它是一种松耦合设计。
这样可以区分设计师的角色,使其专注于 UI 而不是编程/业务逻辑,并允许应用程序在不同的工作流程中工作。

MVVM_Architecture.jpg

如果有兴趣,请在 Silverlight 中 MVVM 的 5 分钟概述 中获取更多详细信息。

本文解释了在使用 MVVM 模式时,如何在 textbox (View) 中使用验证逻辑来设置焦点的问题。

背景

我的一个朋友给了我一个问题并要求我提供一个解决方案,我觉得大多数开发人员都需要它,所以我决定写一篇关于此的文章,这可能会有所帮助。
通常情况下,应用程序有一些控件 (Textbox) 需要最终用户的输入,并且当最终用户执行某些操作(保存或移动到另一个表单)时,我们会在按钮点击时进行验证。现在在 Silverlight 中,借助 ValidatesOnDataErrors=True 属性,显示 UI,textbox 外面有一个红色边框,表明必填字段/无效数据。您可以在下面的屏幕 1 和屏幕 2 中看到。

Normal.jpg

NoFocusInside_TextBox.jpg

但是,如果光标在 textbox 内部闪烁会更好,这样用户就不需要显式地单击鼠标以在 textbox 内部设置焦点,之后他/她才能输入。
因此,这里的兴趣点是在不编写任何 View 代码隐藏文件的情况下,使用 MVVM 模型来实现这一点。
下面的屏幕 3 解释了更多

Focus_Inside_TextBox.jpg

Using the Code

目前 Silverlight 4.0 没有直接提供 CommandManager,借助如何 在 Silverlight 2 中创建命令管理器,因为此命令管理器将在 View 中实现,它会将按钮的命令与点击事件绑定。

<Button Content="Click!"="3"Grid.Column="2"Grid.ColumnSpan="2"
Cmd:CommandManager.CommandEventName="Click"
Cmd:CommandManager.Command="{Binding ClickCommand }" />

目前,此 CommandManager 是作为单独的库创建的,可以在任何其他 Silverlight 类库中使用。

类 TextBoxAttach

现在定义一个类名 TextBoxAttach,它具有 Dependency 属性 (TextBoxControllerProperty)。此属性注册一个函数 OnTextBoxControllerChanged,该函数将在 textbox 控件加载时执行。以下代码中的重点是,当此属性附加到 textbox 时,它会定义一个名为 elements1 的字典,该字典将 textbox 名称存储为 ID

private static readonly Dictionary<string,TextBox> elements1 = 
				new Dictionary<string,TextBox>();

private static void OnTextBoxControllerChanged
	(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as TextBox;
if (element == null)
throw new ArgumentNullException("d");
var newController = e.NewValue as ITextBoxController;
if (newController != null)
{
elements1.Add(element.Name, element);
newController.ClickButton += ClickButton;
}
}

现在,当您单击按钮时,会触发 ClickButton 事件,该事件会检查 textbox 是否为空,以及那些已附加 TextBoxControllerProperty 的 textbox,并且它将在 textbox 内部设置焦点。

private static void ClickButton(ITextBoxController sender)
{
foreach (KeyValuePair<string,TextBox> pair in elements1)
{
TextBox element;
string key = pair.Key;
element = pair.Value;
if (string.IsNullOrEmpty(element.Text))
{
element.Focus();
break;
}
}
}

因此,要使用此 TextBoxAttachtextbox 内部设置焦点,XAML 代码将如下所示

<TextBox x:Name="textBox1" loc:TextBoxAttach.TextBoxController="{Binding}" /> 

类 MyViewModel

类 MyViewModel 继承自 ITextBoxController 并使用 ClickEventhandler 事件,该事件在 ITextBoxController 中定义。并且在这里,在 MyViewModel 的构造函数中,借助 RelayCommand 初始化 ClickCommand,RelayCommand 本身继承自 ICommand。

public MyViewModel()
{
Value1 = "My Text1";
Value2 = "My Text2";

ClickCommand = new RelayCommand(p =>
{
if (ClickButton != null)
ClickButton(this);
});
}

现在为了在 view 中显示验证错误 UI,MyViewModel 类还继承自 IDataErrorInfo,它实现了索引器,也称为 C# 中的智能数组。它非常像定义属性

public string this[string columnName]
{
get 
{
string strMessage = string.Empty;
CustomValidation(ref strMessage, columnName);
return strMessage;
}
}

要使用此验证功能,XAML 代码将如下所示

<TextBox x:Name="textBox1" Text="{Binding Path=Value1,
Mode=TwoWay,ValidatesOnDataErrors=True}" /> 

关注点

  1. MVVM - 如何在文本框中选择文本?
  2. Silverlight 应用程序中的 Model-View-ViewModel。

最后

由于总有改进的空间,如果您有任何意见/投诉/建议,请告诉我。我将尝试解决这些问题,您的反馈将帮助我改进未来在 CodeProject J 上的文章。

历史

  • 发布于 2010 年 9 月 18 日
© . All rights reserved.