WPF: выделение всего текста и установка фокуса на редактируемое текстовое поле ComboBox - PullRequest
3 голосов
/ 28 января 2010

У меня есть WPF ComboBox, у которого есть свойство IsEditable, связанное с моделью представления, которая может включать и выключать его. Когда он включен, я хочу выделить ComboBox и выделить весь текст в редакторе TextBox.

Я не вижу лучшего, чтобы достичь этого. Должен ли я заменить ControlTemplate, создать подкласс базового класса ComboBox и предоставить необходимые свойства, использовать Attached Properties или какой-либо другой подход?

1 Ответ

6 голосов
/ 28 января 2010

У меня есть решение для вас.

Я использую комбинацию Model-View-ViewModel и присоединенного свойства подход.

Во-первых, вам нужно знать систему Messaging в MVVM, чтобы это работало, а также знать ваши Команды . Итак, начиная с Attached Properties, мы начинаем устанавливать событие IsFocused в поле со списком, на которое мы хотели бы сфокусироваться и выделить весь текст.

  #region Select On Focus

  public static bool GetSelectWhenFocused(DependencyObject obj)
  {
    return (bool)obj.GetValue(SelectWhenFocusedProperty);
  }

  public static void SetSelectWhenFocused(DependencyObject obj, bool value)
  {
    obj.SetValue(SelectWhenFocusedProperty, value);
  }

  // Using a DependencyProperty as the backing store for SelectWhenFocused.  This enables animation, styling, binding, etc...
  public static read-only DependencyProperty SelectWhenFocusedProperty =
      DependencyProperty.RegisterAttached("SelectWhenFocused", typeof(bool), typeof(EditableComboBox), new UIPropertyMetadata(OnSelectOnFocusedChanged));

  public static void OnSelectOnFocusedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
  {
    bool SetProperty = (bool)args.NewValue;     

    var comboBox = obj as ComboBox;
    if (comboBox == null) return;

    if (SetProperty)
    {
      comboBox.GotFocus += GotFocused;
      Messenger.Default.Register<ComboBox>(comboBox, Focus);
    }
    else
    {
      comboBox.GotFocus -= GotFocused;
      Messenger.Default.Unregister<ComboBox>(comboBox, Focus);
    }
  }

  public static void GotFocused(object sender, RoutedEventArgs e)
  {
    var comboBox = sender as ComboBox;
    if(comboBox == null) return;

    var textBox = comboBox.FindChild(typeof(TextBox), "PART_EditableTextBox") as TextBox;
    if (textBox == null) return;

    textBox.SelectAll();
  }

  public static void Focus(ComboBox comboBox)
  {
    if(comboBox == null) return;
    comboBox.Focus();
  }
  #endregion

Этот код показывает, когда мы устанавливаем свойство Attached SelectWhenFocused в значение true , оно регистрируется для прослушивания GotFocused Event и выделения всего текста внутри.

Использовать просто:

<ComboBox
  IsEditable="True"
  ComboBoxHelper:EditableComboBox.SelectWhenFocused="True"
  x:Name="EditBox" />

Теперь нам нужна кнопка, которая установит фокус на ComboBox при нажатии.

<Button
  Command="{Binding Focus}"
  CommandParameter="{Binding ElementName=EditBox}"
  Grid.Column="1" >Focus</Button>

Обратите внимание, как CommandParameter связывается с ComboBox его именем EditBox. Это так, когда команда выполняется, только этот ComboBox фокусируется и весь текст выделяется.

В моей ViewModel у меня есть команда Focus , объявленная следующим образом:

public SimpleCommand Focus { get; set; }
public WindowVM()
{
  Focus = new SimpleCommand {ExecuteDelegate = x => Broadcast(x as ComboBox)};
}

Это проверенная и проверенная техника, которая работает для меня. Я надеюсь, что это не излишнее решение вашей проблемы. Удачи.

...