如何将自定义控件的输出发送到文本框
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;
我已经为要在 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;