如何在单击文本框

时间:2016-09-28 10:46:41

标签: c# wpf xaml mvvm

在我的应用程序中,我有一个Usercontrol,它代表一个对象的一些配置。在这里面是一个包含所述对象名称的Texblock。我希望能够单击此Textblock并将其转换为文本框,以便您可以编辑名称。

我希望它有以下3种行为

  1. 按下enter键时设置ViewModel中的值
  2. 可见时获得键盘焦点
  3. 在文本框外部单击鼠标时设置ViewModel中的值(就像组合框一样)
  4. 我目前只停留在3. 如何让我的文本框满足要求3 - 单击文本框设置值我已经实现了一些附件行为以使其他2工作但是可以& #39;让鼠标开始工作。

    我试过以下

    1. 添加了PreviewMouseDown事件 - 只有当鼠标按下文本框
    2. 时才会检测到此事件
    3. 即使在usercontrol中也添加了PreviewMouseDown - 即使单击文本框,这似乎也会受到影响。它也不是我窗口内唯一的用户控件所以它不会在更大的范围内工作。
    4. 添加了一个PreviewMouseDownOutsideCapturedElement - 但永远不会触发它。
    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帖子,但似乎没有人能帮助我,他们都建议将它添加到我无法做到的窗口/用户控件中。

2 个答案:

答案 0 :(得分:0)

我设法找到了解决方案。

基本上我在我的代码中绑定了一个事件,用于文本框的OnGotFocus。当它遇到此方法时,它会将MouseDown和MouseLeave的事件添加到usercontrol。因此,当您单击usercontrol中的任意位置时,它会更新文本框的内容。

如果您离开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;

    }

答案 1 :(得分:0)

我正在WPF Window 中针对内置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中为GotFocus设置TextBox属性。

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

完成。

关于此:

  

添加了PreviewMouseDownOutsideCapturedElement-但永远无法触发。

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