代码之家  ›  专栏  ›  技术社区  ›  Andrew Shepherd

WPF:如果使用助记符激活按钮,则不会发生文本框数据绑定

  •  2
  • Andrew Shepherd  · 技术社区  · 16 年前

    假设您有一个绑定到数据项属性的文本框和一个按钮。 如果在文本框中输入文本,然后用鼠标单击按钮,则以下事件按此顺序发生:

    • 文本从控件写入绑定项
    • 按钮单击事件被触发

    但是,如果使用助记键激活按钮,文本框不会失去焦点。似乎只有当文本框失去焦点时,文本才会从控件写入绑定项。

    是否有已知的解决方法?我想要同样的行为,无论你用鼠标左键点击按钮,用tab键点击按钮并按空格键,还是使用助记符。

    我将提供一个完整的示例。如果您输入单词“Hello”并按下按钮,您将看到一个消息框“WidgetName=Hello”。但如果您随后将其更改为“再见”并按ALT-A,它仍然会显示“WidgetName=Hello”。

    <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 回复  |  直到 16 年前
        1
  •  3
  •   Matt Hamilton    16 年前

    我发现的最简单的解决方案(除了Joseph建议的使用UpdateSourceTrigger属性之外)是将焦点转移到单击事件中的按钮。无论如何“单击”(通过键盘或鼠标)按钮,都会触发按钮的单击事件。

    如果希望文本框保持焦点,可以在变量中保持当前焦点控件,然后将焦点移到按钮,然后立即返回该控件。但这并不理想,因为文本框中插入符号的位置会发生变化。

        2
  •  2
  •   Joseph    16 年前

    你说得对-默认情况下,文本框在焦点丢失之前不会更新绑定。记忆键的激活不是我以前遇到过的:)

    UpdateSourceTrigger 财产)。

        3
  •  1
  •   Andrew Shepherd    16 年前

    一旦我详细解释了这个问题,它就变得显而易见了。

    • 用鼠标单击按钮时,该按钮将接收焦点。这会导致文本框失去焦点,从而触发数据绑定操作。
    • 当您使用助记符时,按钮不接收焦点。

    因此,我们添加了一行代码,以确保按钮具有焦点。

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