如何使用Caliburn.Micro MVVM将焦点设置到控件上
我有一个表单,我想在某些用户操作发生时将焦点设置为文本框。 我知道MVVM的做法是绑定到VM属性,但是TextBox没有允许这种情况发生的属性。 从VM设置焦点的最佳方法是什么?
我创建了一个IResult实现,它可以很好地实现这一目标。 您可以从IResult的ActionExecutionContext获取视图,然后您可以搜索(我按名称搜索)您要关注的控件。
public class GiveFocusByName : ResultBase { public GiveFocusByName(string controlToFocus) { _controlToFocus = controlToFocus; } private string _controlToFocus; public override void Execute(ActionExecutionContext context) { var view = context.View as UserControl; // add support for further controls here List editableControls = view.GetChildrenByType (c => c is CheckBox || c is TextBox || c is Button); var control = editableControls.SingleOrDefault(c => c.Name == _controlToFocus); if (control != null) control.Dispatcher.BeginInvoke(() => { control.Focus(); var textBox = control as TextBox; if (textBox != null) textBox.Select(textBox.Text.Length, 0); }); RaiseCompletedEvent(); } }
我已经省略了一些额外的代码,以便在view
是我可以提供的ChildWindow
时从context
获取view
。
此外,GetChildrenByType是一种扩展方法,这里是野外可用的众多实现之一:
public static List GetChildrenByType (this UIElement element, Func condition) where T : UIElement { List results = new List (); GetChildrenByType (element, condition, results); return results; } private static void GetChildrenByType (UIElement element, Func condition, List results) where T : UIElement { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) { UIElement child = VisualTreeHelper.GetChild(element, i) as UIElement; if (child != null) { T t = child as T; if (t != null) { if (condition == null) results.Add(t); else if (condition(t)) results.Add(t); } GetChildrenByType (child, condition, results); } } }
您的操作将类似于以下内容(在Caliburn.Micro ActionMessage样式中调用)。
public IEnumerable MyAction() { // do whatever yield return new GiveFocusByName("NameOfControlToFocus"); }