Как установить фокус на элемент управления с помощью Caliburn.Micro MVVM - PullRequest
7 голосов
/ 31 декабря 2010

У меня есть форма, и я хочу установить фокус на текстовое поле, когда происходят определенные действия пользователя. Я знаю, что MVVM может делать привязку к свойствам виртуальной машины, однако TextBox не имеет свойства, которое позволит этому произойти. Какой лучший способ установить фокус с виртуальной машины?

1 Ответ

8 голосов
/ 03 февраля 2011

Я создал реализацию IResult, которая довольно хорошо работает для достижения этой цели.Вы можете получить представление из ActionExecutionContext объекта IResult, которое затем можно будет искать (я ищу по имени) для элемента управления, на который вы хотите сфокусироваться.

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. Я могу предоставить, если вам потребуется.

Также GetChildrenByType - это метод расширения, вот одна из многих реализаций, доступных в wild:

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);
        }
    }
}

Тогда ваше действие будет выглядеть примерно так (вызывается в стиле Caliburn.Micro ActionMessage).

public IEnumerable<IResult> MyAction()
{
    // do whatever
    yield return new GiveFocusByName("NameOfControlToFocus");
}
...