WPF KeyBinding 命令未在自定义控件中触发
WPF KeyBinding Command not triggering in Custom Control
我正在构建 WPF 自定义控件(注意:不是 用户控件)。控件的c#代码定义如下:
using System.Windows;
using System.Windows.Controls;
using MvvmFoundation.Wpf;
namespace TextBoxWithInputBinding
{
public class AutoComp : Control
{
static AutoComp()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoComp), new FrameworkPropertyMetadata(typeof(AutoComp)));
}
public AutoComp()
{
DownCommand = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("Down");
});
PressedCommand = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("Pressed");
});
}
public RelayCommand DownCommand
{
get { return (RelayCommand)GetValue(DownCommandProperty); }
set { SetValue(DownCommandProperty, value); }
}
public static readonly DependencyProperty DownCommandProperty =
DependencyProperty.Register("DownCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));
public RelayCommand PressedCommand
{
get { return (RelayCommand)GetValue(PressedCommandProperty); }
set { SetValue(PressedCommandProperty, value); }
}
public static readonly DependencyProperty PressedCommandProperty =
DependencyProperty.Register("PressedCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));
}
}
我为Generic.xaml中的控件定义模板如下:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBoxWithInputBinding">
<Style TargetType="{x:Type local:AutoComp}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AutoComp}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
>
<StackPanel>
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>
</TextBox.InputBindings>
</TextBox>
<Button Content="Press me" Command="{TemplateBinding PressedCommand}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
当我按下 "Press me" 按钮时,PressedCommand 被触发(单词 "Pressed" 出现在输出 window 中 - 但是,当我在 TextBox 中键入并按下向下键时, 没有任何反应。
我需要做什么才能触发 DownCommand?
所以我找到了答案:我需要常规绑定而不是模板绑定:我替换了
<KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>
和
<KeyBinding Key="Down"
Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>
我仍然想知道为什么 Button 绑定与 TemplateBinding 一起使用,而 TextBox KeyBinding 却不行!!!
正如您已经发现的那样,您应该将 TemplateBinding
替换为通常的绑定标记并使用 {RelativeSource TemplatedParent}
<KeyBinding Key="Down"
Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>
I would still like to know why the Button binding works with TemplateBinding but the TextBox KeyBinding does not?
因为TemplateBinding
经过优化,与使用普通的Binding
相比有一些限制。例如,它只直接在 ControlTemplates
的可视化树中起作用,但在 DataTrigger
和 KeyBinding
中不起作用。
您可以在此处找到更多相关信息:
WPF TemplateBinding vs RelativeSource TemplatedParent
我正在构建 WPF 自定义控件(注意:不是 用户控件)。控件的c#代码定义如下:
using System.Windows;
using System.Windows.Controls;
using MvvmFoundation.Wpf;
namespace TextBoxWithInputBinding
{
public class AutoComp : Control
{
static AutoComp()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoComp), new FrameworkPropertyMetadata(typeof(AutoComp)));
}
public AutoComp()
{
DownCommand = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("Down");
});
PressedCommand = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("Pressed");
});
}
public RelayCommand DownCommand
{
get { return (RelayCommand)GetValue(DownCommandProperty); }
set { SetValue(DownCommandProperty, value); }
}
public static readonly DependencyProperty DownCommandProperty =
DependencyProperty.Register("DownCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));
public RelayCommand PressedCommand
{
get { return (RelayCommand)GetValue(PressedCommandProperty); }
set { SetValue(PressedCommandProperty, value); }
}
public static readonly DependencyProperty PressedCommandProperty =
DependencyProperty.Register("PressedCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));
}
}
我为Generic.xaml中的控件定义模板如下:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBoxWithInputBinding">
<Style TargetType="{x:Type local:AutoComp}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AutoComp}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
>
<StackPanel>
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>
</TextBox.InputBindings>
</TextBox>
<Button Content="Press me" Command="{TemplateBinding PressedCommand}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
当我按下 "Press me" 按钮时,PressedCommand 被触发(单词 "Pressed" 出现在输出 window 中 - 但是,当我在 TextBox 中键入并按下向下键时, 没有任何反应。
我需要做什么才能触发 DownCommand?
所以我找到了答案:我需要常规绑定而不是模板绑定:我替换了
<KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>
和
<KeyBinding Key="Down"
Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>
我仍然想知道为什么 Button 绑定与 TemplateBinding 一起使用,而 TextBox KeyBinding 却不行!!!
正如您已经发现的那样,您应该将 TemplateBinding
替换为通常的绑定标记并使用 {RelativeSource TemplatedParent}
<KeyBinding Key="Down"
Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>
I would still like to know why the Button binding works with TemplateBinding but the TextBox KeyBinding does not?
因为TemplateBinding
经过优化,与使用普通的Binding
相比有一些限制。例如,它只直接在 ControlTemplates
的可视化树中起作用,但在 DataTrigger
和 KeyBinding
中不起作用。
您可以在此处找到更多相关信息:
WPF TemplateBinding vs RelativeSource TemplatedParent