处理背后的自定义控制代码中的事件 [英] Handle Events in Custom Control Code Behind

查看:55
本文介绍了处理背后的自定义控制代码中的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,这可能是一个很愚蠢的问题,但我已经搜索了很长时间,但找不到有效的解决方案...

Ok, that probably is a pretty dumb question but I have searched quite a while but could not find a solution for this that works...

我有一个自 Control 继承的自定义控件,其中应包含自动化代码.

I have a Custom control inherited from Control, which shall include code behind automation.

对于序言,请选择控件 TextBox 的所有文本,或者在更改 TextBox 的内容时生成紧密匹配的列表.

For examble select all text of a controls TextBox when selected, or generate a list of close matches when the content of that TextBox is changed.

public class vokDataGridEdit : Control
{
    static vokDataGridEdit()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(vokDataGridEdit), new FrameworkPropertyMetadata(typeof(vokDataGridEdit)));

        // Events internal to control (??? found on some how-to's)
        EventManager.RegisterClassHandler(typeof(vokDataGridEdit), UIElement.GotKeyboardFocusEvent, new RoutedEventHandler(OnSelectContent), true);
    }

    // Dependecy Properties ...

    // The Event that shall Fire when the TextBox gets Focus / Editing Mode
    public static void SelectContent(object sender, RoutedEventArgs e)
    {
        if (sender is TextBox tb)
        {
            tb.SelectAll();
        }
    }
}

以及控件样式模板:

<ResourceDictionary xmlns       = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x     = "http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:ccont = "clr-namespace:App.Controls">

    <!-- Default style for the Validation Buttons -->
    <Style TargetType="{x:Type ccont:vokDataGridEdit}">

        <Setter Property="SnapsToDevicePixels"  Value="true" />

        <Setter Property="Template">
            <Setter.Value>

                <ControlTemplate TargetType="{x:Type ccont:vokDataGridEdit}">

                    <TextBox Text                               = "{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=ccont:vokDataGridEdit}}"
                             BorderThickness                    = "0"
                             ContextMenuService.Placement       = "Right"
                             ContextMenuService.PlacementTarget = "{Binding Path=., RelativeSource={RelativeSource Self}}"
                             GotKeyboardFocus                   = "SelectContent">

                        <TextBox.ContextMenu>
                            <ContextMenu>
                                <ContextMenu.Template>
                                    <ControlTemplate>

                                        <Border CornerRadius    = "5"
                                                Background      = "LightGray"
                                                BorderThickness = "1" 
                                                BorderBrush     = "Gray"
                                                Padding         = "2">

                                            <StackPanel Orientation="Vertical">

                                                <!-- Title -->
                                                <TextBlock Text="Test" />

                                                <!-- TODO: List of matches -->
                                                <TextBox Text               = "{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=ccont:vokDataGridEdit}}" 
                                                         BorderThickness    = "0" />

                                            </StackPanel>

                                        </Border>

                                    </ControlTemplate>
                                </ContextMenu.Template>
                            </ContextMenu>
                        </TextBox.ContextMenu>

                    </TextBox>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

问题1:我如何绑定事件 SelectContent (要在焦点获得时选择所有 TextBox 内容,nb:这是一部分 CellEditingTemplate DataGrid )到 GotKeyboardFocus ?在Apps代码中,事件通常正常,但是对于自定义控件而言,它们不起作用,因为样式实际上没有隐藏的代码" ...

Question 1: How can I bind the event SelectContent (to select all TextBox content when it get focus, nb: it is part of a DataGrid for the CellEditingTemplate) to GotKeyboardFocus? Events are normaly fine in the Apps code, but for the Custom Control they do not work as there is no "Code Behind" really for the Style...

问题2:假设我有一个包含单词数组的依赖项属性.基于 TextBox 的内容,我想从Dependency属性的Array中选择一些单词,并将它们传递到Custom Control(内容控件)中的 ListBox ListBox 的列表只能由自定义控件"管理,而不是由使用该控件的任何人管理.关于如何实现此功能,是否存在首选/规范的MVVM模式?

Question 2: Assuming I have a dependency Property containing an array of words. Based on the content of the TextBox, I would like to select a few words from the Array in the Dependency Property and pass them to a ListBox in the Custom Control (the Content of the ListBox shall only be managed by the Custom Control, not by anyone using that control. Is there a prefered/canonical MVVM schema on how to implement this?

推荐答案

部分解决方案:

最后,我在直接控件上得到了要起作用的事件( ContextMenu 中的控件仍然没有EventHandlers ...).

Finaly I got event on the direct controls to work (controls in a ContextMenu still don't get EventHandlers...).

显然,该点是使用 GetTemplateChild()以便按名称获取TextBox,然后关联事件处理程序:

Apparently the point was using GetTemplateChild() in order to get the TextBox by name, and then associate the Event handlers:

<ResourceDictionary xmlns       = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x     = "http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:ccont = "clr-namespace:App.Controls">

    <!-- Default style for the Validation Buttons -->
    <Style TargetType="{x:Type ccont:vokDataGridEdit}">

        <Setter Property="SnapsToDevicePixels"  Value="true" />

        <Setter Property="Template">
            <Setter.Value>

                <ControlTemplate TargetType="{x:Type ccont:vokDataGridEdit}">

                    <TextBox Text                               = "{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=ccont:vokDataGridEdit}}"
                             BorderThickness                    = "0"
                             ContextMenuService.Placement       = "Right"
                             ContextMenuService.PlacementTarget = "{Binding Path=., RelativeSource={RelativeSource Self}}"
                             x:Name                             = "TextBox">

                        <TextBox.ContextMenu>
                            <ContextMenu x:Name="Menu">
                                <ContextMenu.Template>
                                    <ControlTemplate>

                                        <Border CornerRadius    = "5"
                                                Background      = "LightGray"
                                                BorderThickness = "1" 
                                                BorderBrush     = "Gray"
                                                Padding         = "2">

                                            <StackPanel Orientation="Vertical">

                                                <!-- Title -->
                                                <TextBlock Text="Test" x:Name = "Test" />

                                                <!-- TODO: List of matches -->
                                                <TextBox Text               = "{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=ccont:vokDataGridEdit}}" 
                                                         BorderThickness    = "0" />

                                            </StackPanel>

                                        </Border>

                                    </ControlTemplate>
                                </ContextMenu.Template>
                            </ContextMenu>
                        </TextBox.ContextMenu>

                    </TextBox>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

和代码(未显示依赖项属性):

And Code (Dependency Properties not shown):

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace App.Controls
{
    /// <summary>
    /// DataGrid Edit control (see: https://www.c-sharpcorner.com/article/wpf-routed-events/ for RoutedEvents)
    /// </summary>
    public class vokDataGridEdit : Control
    {
        static vokDataGridEdit()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(vokDataGridEdit), new FrameworkPropertyMetadata(typeof(vokDataGridEdit)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // Demo purpose only, check for previous instances and remove the handler first  
            if (this.GetTemplateChild("TextBox") is TextBox button)
            {
                button.PreviewMouseLeftButtonDown   += this.SelectContentPreparation;
                button.GotKeyboardFocus             += this.SelectContent;
                button.MouseDoubleClick             += this.SelectContent;
                //button.GotFocus                     += this.SelectContent;
            }
        }

        /// <summary>
        /// Prepare the Control to ensure it has focus before subsequent event fire
        /// </summary>
        private void SelectContentPreparation(object sender, MouseButtonEventArgs e)
        {
            if (sender is TextBox tb)
            {
                if (!tb.IsKeyboardFocusWithin)
                {
                    e.Handled = true;
                    tb.Focus();
                }
            }
        }

        private void SelectContent(object sender, RoutedEventArgs e)
        {
            if (sender is TextBox tb)
            {
                e.Handled = true;
                tb.SelectAll();
            }
        }
    }
}

这篇关于处理背后的自定义控制代码中的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆