WPF: привязка данных TextBox не происходит, если вы активируете кнопку с мнемоникой - PullRequest
2 голосов
/ 18 сентября 2009

Предположим, у вас есть текстовое поле, привязанное к свойству элемента данных, и кнопка. Если вы вводите текст в текстовое поле, а затем нажимаете кнопку мыши, в следующем порядке происходят следующие события:

  • Текст записывается из элемента управления в связанный элемент
  • Запущено событие нажатия кнопки

Однако, если вы активируете кнопку с помощью мнемонической клавиши, текстовое поле не теряет фокус. Кажется, что текст записывается из элемента управления в связанный элемент только тогда, когда текстовое поле теряет фокус.

Есть ли известный обходной путь к этому? Мне нужно такое же поведение, независимо от того, щелкнете ли вы левой кнопкой мыши по кнопке, перейдете к кнопке и нажмете пробел или используете мнемонику.

Я приведу полный пример. Если вы введете слово «Hello» и нажмете кнопку, вы получите окно сообщения «WidgetName = Hello». Но если вы затем изменили его на «Goodbye» и нажали ALT-A, он все равно будет «WidgetName = Hello».

Вот код XAML

<Window x:Class="BindingOrder.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BindingOrder"
    Title="Window1" Height="79" Width="282">
    <Window.Resources>
        <local:Widget x:Key="Widget" />
    </Window.Resources>
    <StackPanel Orientation="Horizontal" Height="30" VerticalAlignment="Top">
        <TextBox 
            Width="200" 
            Margin="3, 3, 3, 3" 
            Text="{Binding Source={StaticResource Widget}, Path=WidgetName}" />
        <Button  
            Click="OnApplyClicked" 
            Margin="3, 3, 3, 3">
            _Apply
        </Button>        
    </StackPanel>
</Window>

и вспомогательный код:

using System;
using System.Windows;

namespace BindingOrder
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void OnApplyClicked(object sender, RoutedEventArgs e)
        {
            Widget w = (Widget)this.Resources["Widget"];
            MessageBox.Show(string.Format("WidgetName={0}", w.WidgetName));
        }
    }

    public class Widget
    {
        public string WidgetName { get; set; }
    }
}

Ответы [ 3 ]

3 голосов
/ 18 сентября 2009

Самое простое решение, которое я нашел (кроме использования свойства UpdateSourceTrigger, как предложил Джозеф), - это сместить фокус на кнопку в событии Click. Событие Click кнопки запускается независимо от того, как кнопка «нажата» (с помощью клавиатуры или мыши).

Если вы хотите, чтобы TextBox сохранял фокус, вы могли бы удерживать фокусированный в данный момент элемент управления в переменной, затем переместить фокус на кнопку и сразу же вернуться к этому элементу управления. Хотя это и не идеально, потому что позиция каретки в TextBox изменится.

2 голосов
/ 18 сентября 2009

Вы правы - текстовое поле не обновляет привязку, пока фокус не будет потерян по умолчанию. Активация с помощью мнемонического ключа - это не то, что мне приходило в голову раньше:)

Это прискорбно, но вы можете установить привязку для обновления, когда пользователь печатает (см. Свойство UpdateSourceTrigger ).

1 голос
/ 18 сентября 2009

Как только я подробно объяснил вопрос, становится очевидным.

  • Когда вы нажимаете кнопку мышью, кнопка получает фокус. Это приводит к тому, что TextBox теряет фокус, что вызывает действие привязки данных.
  • Кнопка не получает фокус при использовании мнемоники.

Если кнопка получает фокус при использовании мнемоники, проблема решена.

Итак, мы добавляем одну строку кода, чтобы кнопка была в фокусе.

    private void OnApplyClicked(object sender, RoutedEventArgs e)
    {
        ((UIElement)sender).Focus();
        Widget w = (Widget)this.Resources["Widget"];
        MessageBox.Show(string.Format("WidgetName={0}", w.WidgetName));
    }
...