如何将自定义控件的输出发送到文本框

How to send output from a custom control to a textbox

我已经为要在 WPF 应用程序中使用的虚拟键盘创建了一个按钮布局,为了使其可重用,我想我可以给它一个 Target 类型 属性 的依赖项 TextBox 将键盘的输出发送到。我也为我的键盘按钮做了一个自定义控件,所以它们有一个 Output 属性.

将按钮的输出附加到目标文本框的当前文本内容的最佳方法是什么?我应该使用事件或命令,还是其他?

XAML 输出 window:

<UserControl x:Class="Project.Views.DataInput.DataInputExample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Project.Views.DataInput"
             xmlns:cc="clr-namespace:Project.CustomControls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Text="{Binding ElementName=Keyboard, Path=Output}" />
        <cc:Keyboard x:Name="Keyboard" Grid.Row="1" />
    </Grid>
</UserControl>

XAML 对于 Keyboard:

<Style TargetType="{x:Type local:Keyboard}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Keyboard}">
                <Border ...>
                    <Grid x:Name="PART_Keyboard" ...>
                        <Grid.RowDefinitions>
                            ...
                        </Grid.RowDefinitions>
                        <Grid x:Name="FirstRow" ...>
                            <Grid.ColumnDefinitions>
                                ...
                            </Grid.ColumnDefinitions>
                            <local:KeyboardButton Output="q" Click="BtnClick" />
                            ...
                        </Grid>
                        ...
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

CS Keyboard:

public class Keyboard : Control
{
    public string Output
    {
        get { return (string)GetValue(OutputProperty); }
        set { SetValue(OutputProperty, value); }
    }

    public static readonly DependencyProperty OutputProperty =
        DependencyProperty.Register("Output", typeof(string), typeof(Keyboard), new PropertyMetadata(""));

    static Keyboard()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Keyboard), new FrameworkPropertyMetadata(typeof(Keyboard)));
    }
}

CS KeyboardButton:

public class KeyboardButton : ImageTextButton
{
    public string Output
    {
        get { return (string)GetValue(OutputProperty); }
        set { SetValue(OutputProperty, value); }
    }

    public static readonly DependencyProperty OutputProperty =
        DependencyProperty.Register(
            "Output",
            typeof(string),
            typeof(KeyboardButton),
            new PropertyMetadata("")
            );

    static KeyboardButton()
    {
        // DefaultStyleKeyProperty.OverrideMetadata(typeof(KeyboardButton), new FrameworkPropertyMetadata(typeof(KeyboardButton)));
    }

    private void BtnClick(object sender, RoutedEventArgs e)
    {
        var button = (KeyboardButton)sender;
        var keyboard = (Keyboard)(button.Parent);
        keyboard.Output += button.Output;
    }
}

我会强调,你的虚拟键盘更像是一个 ContentControl 而不是一个按钮,但那是另一回事。

在你的服装虚拟键盘控件中你做了一个属性:

public string EnteredText {get; private set; }

在您的虚拟键盘中确保此 属性 始终包含当前输入的文本。当你有一个 window 时,你想在文本框中显示输入的文本,可以通过以下方式完成:

<local:VirtualKeyboard x:Name="MyVirtualKeyboard" />
<TextBox Text="{Binding ElementName=MyVirtualKeyboard, Path=EnteredText}" />

然后通过绑定魔法,文本框将包含用户输入的文本。您还可以使用许多其他类型的控件。例如,一个 TextBlock 将是一个显而易见的候选者。

因为 KeyboardButtons 被放置在虚拟键盘控件中,我们需要一个辅助方法,它在许多其他情况下也很方便:

  public static P FindVisualParent<P>(DependencyObject Dep) where P : DependencyObject
  {
     while (Dep != null)
     {
        if ((Dep is Visual) || (Dep is System.Windows.Media.Media3D.Visual3D))
        {
           if (Dep is P) return (Dep as P);
           Dep = VisualTreeHelper.GetParent(Dep);
        }
        else
        {
           Dep = LogicalTreeHelper.GetParent(Dep);
        }
     }
     return (null);
  }

然后在 KeyboardButton 用户控件中使用此方法:

public override void OnApplyTemplate()
{
   // Base call
   base.OnApplyTemplate();
   // Get the virtual keyboard control
   this.virtualKeyboard = FindVisualParent<VirtualKeyboard>(this);
   // Set the click event
   this.Click += (s,e) => { this.virtualKeyboard.EnteredText += this.Output; };
}

并且在KeyboardButton控件中也定义了这个成员变量:

private VirtualKeyboard virtualKeyboard;