我有一个表单,我想在某些用户操作发生时将焦点设置为文本框。我知道MVVM的做法是绑定到VM属性,但是TextBox没有允许这种情况发生的属性。从VM设置焦点的最佳方法是什么?
答案 0 :(得分:8)
我创建了一个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<Control> editableControls =
view.GetChildrenByType<Control>(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
context
我可以提供view
,我已经省略了一些额外的代码来从ChildWindow
获取public static List<T> GetChildrenByType<T>(this UIElement element,
Func<T, bool> condition) where T : UIElement
{
List<T> results = new List<T>();
GetChildrenByType<T>(element, condition, results);
return results;
}
private static void GetChildrenByType<T>(UIElement element,
Func<T, bool> condition, List<T> 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<T>(child, condition, results);
}
}
}
。
此外,GetChildrenByType是一种扩展方法,这是野外可用的众多实现之一:
public IEnumerable<IResult> MyAction()
{
// do whatever
yield return new GiveFocusByName("NameOfControlToFocus");
}
您的操作将类似于以下内容(在Caliburn.Micro ActionMessage样式中调用)。
{{1}}