如何在单击关闭文本框时更新文本框的绑定

本文关键字:文本 绑定 更新 单击 | 更新日期: 2023-09-27 18:09:16

在我的应用程序中,我有一个Usercontrol,它代表一个对象的一些配置。其中是一个Texblock,其中包含了所述对象的名称。我希望能够点击这个Textblock并把它变成一个文本框,这样你就可以编辑名字了。

我希望它有以下3个行为

  1. 在按enter键时设置ViewModel中的值
  2. 当键盘变得可见时获得键盘焦点
  3. 设置当鼠标在文本框外点击时ViewModel中的值(就像组合框一样)

,我目前被困在3。我怎么能让我的文本框满足要求3 -点击文本框设置值我已经实现了一些附件行为,使其他2个工作,但不能让鼠标一个工作。

我已经尝试了以下

  1. 增加了PreviewMouseDown事件-这似乎只有当鼠标按下在文本框
  2. 时才会被检测到
  3. 添加PreviewMouseDown甚至在用户控制-这似乎得到击中,即使当文本框被点击。它也不是我窗口内唯一的用户控件,所以它不会在更大的范围内工作。
  4. 添加了previewmousedownoutside ecapturedelement -但永远不能让它触发
  5. 同时失去对UpdateSourceTrigger和作为一个事件的关注-这只在你点击一个不同的输入字段而不是直接点击
  6. 时才有效。

文本框的代码如下所示。

            <TextBox x:Name="text" VerticalAlignment="Center"
                 Margin="5,2,0,0"
                 Text="{Binding Name, Mode=TwoWay}"
                 Visibility="{Binding IsEditingName, Converter={StaticResource VisConverter}, FallbackValue=Collapsed}"
                 b:FocusBehaviours.ShouldFocusWhenVisible="True"
                 b:InputBehaviours.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>

我看过无数的SO帖子,似乎没有一个能帮助我解决这个问题,他们都建议把它添加到窗口/用户控制,我不能这样做。

如何在单击关闭文本框时更新文本框的绑定

我终于找到了解决办法。

基本上,我在文本框的OnGotFocus后面绑定了一个事件。当它碰到这个方法时,它会给用户控件添加一个MouseDown和MouseLeave事件。所以当你点击usercontrol的任意位置时它会更新文本框的内容

如果你离开了用户控件的边界,那么你想把鼠标向下事件移到窗口本身。类似地,当你移动回用户控件时,你想要删除窗口上的鼠标下降事件,或者当你离开后单击回文本框时,它会设置值。

我在这里添加了我的代码,希望它将清楚谁可能有类似的问题。

我相信一定有比使用后面的代码更好的方法,但我不认为我在这里违反了MVVM原则,所以我认为我是安全的。

        private void View_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        updateTextbox();
    }
    private void View_OnMouseLeave(object sender, MouseEventArgs e)
    {
        Window parentWindow = Window.GetWindow(this);
        if (parentWindow != null)
        {
            Mouse.AddPreviewMouseDownHandler(parentWindow, ParentWindow_OnMouseDown);
        }
    }
    private void View_OnMouseEnter(object sender, MouseEventArgs e)
    {
        Window parentWindow = Window.GetWindow(this);
        if (parentWindow != null)
        {
            Mouse.RemovePreviewMouseDownHandler(parentWindow, ParentWindow_OnMouseDown);
        }
    }
    private void ParentWindow_OnMouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        Window parentWindow = Window.GetWindow(this);
        if (parentWindow != null)
        {
            Mouse.RemovePreviewMouseDownHandler(parentWindow, ParentWindow_OnMouseDown);
        }
        updateTextbox();
    }
    private void updateTextbox()
    {
        Keyboard.Focus(this);
    }
    private void Text_OnGotFocus(object sender, RoutedEventArgs e)
    {
        MouseDown += View_OnMouseDown;
        MouseLeave += View_OnMouseLeave;
        MouseEnter += View_OnMouseEnter;
    }
    private void Text_OnLostFocus(object sender, RoutedEventArgs e)
    {
        BindingOperations.GetBindingExpression(text, TextBox.TextProperty).UpdateSource();
        MouseDown -= View_OnMouseDown;
        MouseLeave -= View_OnMouseLeave;
        MouseEnter -= View_OnMouseEnter;
    }

我在WPF 窗口为内置的TextBox这样做,以便在用户点击外部时做一些事情。该方法可以很容易地应用于WPF/UWP的WindowPage

// In your `XxxWindow.xaml.cs`(or corresponding class in VB):
public partial class XxxWindow : Window {
    ...
    //  The event handler delegate for handling click outsides a TextBox.
    private readonly MouseButtonEventHandler windowWideMouseButtonEventHandler;
    // Add something in the constructor or any initialization methods.
    public MainWindow() {
        ...
        // Initialize the handler.
       windowWideMouseButtonEventHandler = new MouseButtonEventHandler(OnWindowWideMouseEvent);//+
    }
    ...
    ...
    // Whenever the text box got focus, begin listening to window-wide clicks.
    // This method shall be bounded in xaml or elsewhere.
    // Added method
    private void SearchBox_GotFocus(object sender, RoutedEventArgs e) {
        AddHandler(Window.PreviewMouseDownEvent, windowWideMouseButtonEventHandler);
    }
    // The handler method
    // Added method
    private void OnWindowWideMouseEvent(object sender, MouseButtonEventArgs e) {
        // Exclude the text box itself.
        if (!FocusManager.GetFocusedElement(this).IsMouseOver) {
            // Unregister the already-used handler.
            RemoveHandler(Window.PreviewMouseDownEvent, windowWideMouseButtonEventHandler);
            // Do something, save text or cancel focus.
        }
    }
    ...
}

XxxWindow.xaml中为TextBox设置GotFocus属性。

<TextBox ... GotFocus="SearchBox_GotFocus">
...
</TextBox>

关于这个:

添加了previewmousedownoutside ecapturedelement -但不能让它触发。

我只有在调用CaptureMouse时显示MessageBox时才会触发它,这在现实世界中是不应该发生的。也许这是为弹出窗口设计的