Я пытаюсь найти способ сделать что-то подобное, используя строгий MVVM. Если это что-то, что нельзя делать с помощью XAML (в MVVM), тогда это нормально. Но я хотел бы видеть какую-то документацию о том, как она вписывается в шаблон MVVM, выполняющий его за пределами XAML.
Вы считали, что используете приложенное поведение. Они просты в реализации и используют AttachedProperty. Хотя он по-прежнему требует кода, этот код абстрагируется в classе и может быть повторно использован. Они могут устранить необходимость «кода позади» и часто используются с шаблоном MVVM.
Попробуйте это и посмотрите, работает ли оно для вас.
public class EventFocusAttachment { public static Control GetElementToFocus(Button button) { return (Control)button.GetValue(ElementToFocusProperty); } public static void SetElementToFocus(Button button, Control value) { button.SetValue(ElementToFocusProperty, value); } public static readonly DependencyProperty ElementToFocusProperty = DependencyProperty.RegisterAttached("ElementToFocus", typeof(Control), typeof(EventFocusAttachment), new UIPropertyMetadata(null, ElementToFocusPropertyChanged)); public static void ElementToFocusPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var button = sender as Button; if (button != null) { button.Click += (s, args) => { Control control = GetElementToFocus(button); if (control != null) { control.Focus(); } }; } } }
И тогда в вашем XAML сделайте что-нибудь вроде …
Я не рядом с визуальной студией, поэтому я не могу сейчас попробовать это прямо сейчас, но с головы до ног вы должны сделать что-то вроде этого:
Ниже приведен следующий вопрос (заданный совсем недавно): как установить автофокус только в xaml? который содержит этот метод, и несколько разных идей о том, как его использовать.
Вы также можете использовать поведение WPF …
public class FocusElementAfterClickBehavior : Behavior { private ButtonBase _AssociatedButton; protected override void OnAttached() { _AssociatedButton = AssociatedObject; _AssociatedButton.Click += AssociatedButtonClick; } protected override void OnDetaching() { _AssociatedButton.Click -= AssociatedButtonClick; } void AssociatedButtonClick(object sender, RoutedEventArgs e) { Keyboard.Focus(FocusElement); } public Control FocusElement { get { return (Control)GetValue(FocusElementProperty); } set { SetValue(FocusElementProperty, value); } } // Using a DependencyProperty as the backing store for FocusElement. This enables animation, styling, binding, etc... public static readonly DependencyProperty FocusElementProperty = DependencyProperty.Register("FocusElement", typeof(Control), typeof(FocusElementAfterClickBehavior), new UIPropertyMetadata()); }
Прикрепите поведение WPF к кнопке и элементу связывания, для которого вы хотите установить фокус:
Таким образом, у вас нет кода, и он может использоваться повторно для любого элемента управления, который наследуется от ButtonBase.
Надеюсь, это поможет кому-то.
вам понадобится TriggerAction чтобы вызвать метод Focus () на нужном элементе управления.
public class SetFocusTrigger : TargetedTriggerAction { protected override void Invoke(object parameter) { if (Target == null) return; Target.Focus(); } }
Чтобы настроить фокус на элемент управления, вы поместите коллекцию триггеров после LayoutRoot (или любого элемента управления), выберите событие в качестве триггера и выберите SetFocusTrigger в качестве classа для запуска. В объявлении SetFocusTrigger вы помещаете имя элемента управления, которому хотите получить фокус, с использованием свойства TargetName.
Это то, что вы хотите?
C #:
public void MoveFocusOnClick(object sender, RoutedEventArgs e) { Keyboard.Focus(txtName); // Or your own logic }
Это то же самое, что и решение Яна Оукса, но я сделал несколько незначительных изменений.
Тип кнопки может быть более общим, а именно ButtonBase , для обработки большего числа случаев, таких как ToggleButton .
Тип цели также может быть более общим, а именно UIElement . С технической точки IInputElement , это может быть IInputElement , я полагаю.
Я сделал статичный обработчик событий, так что он не будет генерировать время выполнения во время выполнения. Чтобы он оставался неподвижным, я вытащил его из лямбды.
Огромное спасибо Яну.
public sealed class EventFocusAttachment { [DebuggerStepThrough] public static UIElement GetTarget(ButtonBase b) { return (UIElement)b.GetValue(TargetProperty); } [DebuggerStepThrough] public static void SetTarget(ButtonBase b, UIElement target) { b.SetValue(TargetProperty, target); } public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("Target", typeof(UIElement), typeof(EventFocusAttachment), new UIPropertyMetadata(null, TargetPropertyChanged)); public static void TargetPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs _) { ButtonBase bb; if ((bb = o as ButtonBase) != null) bb.Click += handler; } static void handler(Object o, RoutedEventArgs _) { UIElement target; if ((target = GetTarget((ButtonBase)o)) != null) target.Focus(); } };
Использование в основном такое же, как и выше:
Обратите внимание, что событие может настроить целевую / фокусировку самой исходной кнопки.