如何使用Caliburn.Micro MVVM将焦点设置为控件

时间:2010-12-31 17:08:37

标签: c# silverlight mvvm caliburn.micro

我有一个表单,我想在某些用户操作发生时将焦点设置为文本框。我知道MVVM的做法是绑定到VM属性,但是TextBox没有允许这种情况发生的属性。从VM设置焦点的最佳方法是什么?

1 个答案:

答案 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}}