[英]KeyBinding works as UserControl but not when pusing property element syntax in XAML
正如标题所述,我在使用属性元素语法时无法使KeyBinding
起作用。 通过工作我的意思是使用Ctrl+Del
组合键来更改列表框的背景颜色。 可以使用键组合或单击按钮,这两个按钮都会调用该命令,但从不调用该命令。 在调试模式下设置断点时,永远不会遇到断点。
我已经遵循文档中的InputBinding类示例 ,并且只能在使用UserControl
时使KeyBinding
工作,并且想要理解为什么会这样,以及我做错了什么 。
下面是一个MVCE,用于表示使用属性元素语法声明的代码不起作用。 注释掉是UserControl
的一行,它封装了StackPanel
并允许KeyBinding
工作。 依赖于注释掉每个PropertyElementSyntax
区域并取消注释MainWindow.xaml.cs
后面代码中的每个UserControlSyntax
区域。
MainWindow.xaml:
<Window x:Class="LearningKeyBindingWPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LearningKeyBindingWPFApp"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="300">
<!--<local:UserControl1 x:Name="CustomColorPicker" />-->
<StackPanel Margin="0,40,0,0">
<StackPanel.InputBindings>
<KeyBinding Command="{Binding ChangeColorCommand}"
CommandParameter="{Binding ElementName=ColorPicker, Path=SelectedItem}"
Key="{Binding ChangeColorCommand.Key}"
Modifiers="{Binding ChangeColorCommand.ModifierKeys}" />
<MouseBinding Command="{Binding ChangeColorCommand}"
CommandParameter="{Binding ElementName=ColorPicker, Path=SelectedItem}"
MouseAction="{Binding ChangeColorCommand.MouseAction}" />
</StackPanel.InputBindings>
<Button Content="Change Color"
Command="{Binding ChangeColorCommand}"
CommandParameter="{Binding ElementName=ColorPicker, Path=SelectedItem}" />
<ListBox Name="ColorPicker"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
SelectedIndex="0">
<sys:String>Red</sys:String>
<sys:String>Green</sys:String>
<sys:String>Blue</sys:String>
<sys:String>Yellow</sys:String>
<sys:String>Orange</sys:String>
<sys:String>Purple</sys:String>
</ListBox>
</StackPanel>
</Window>
MainWindow.xaml.cs的代码隐藏:
public MainWindow()
{
DataContext = this;
InitializeComponent();
InitializeCommand();
#region UserControlSyntax
//CustomColorPicker.ColorPicker.Focus();
#endregion
#region PropertyElementSyntax
ColorPicker.Focus();
#endregion
}
public SimpleDelegateCommand ChangeColorCommand { get; private set; }
private SolidColorBrush _originalColor;
private void InitializeCommand()
{
#region UserControlSyntax
//_originalColor = (SolidColorBrush)CustomColorPicker.ColorPicker.Background;
#endregion
#region PropertyElementSyntax
_originalColor = (SolidColorBrush)ColorPicker.Background;
#endregion
ChangeColorCommand = new SimpleDelegateCommand(ChangeColor)
{
Key = Key.Delete,
ModifierKeys = ModifierKeys.Control
};
}
private void ChangeColor(object colorString)
{
if (colorString == null)
{
return;
}
var selectedColor = SelectedColor((string)colorString);
#region UserControlSyntax
//if (CustomColorPicker.ColorPicker.Background == null)
//{
// CustomColorPicker.ColorPicker.Background = selectedColor;
// return;
//}
//CustomColorPicker.ColorPicker.Background = ((SolidColorBrush)CustomColorPicker.ColorPicker.Background).Color == selectedColor.Color
// ? _originalColor
// : selectedColor;
#endregion
#region PropertyElementSyntax
if (ColorPicker.Background == null)
{
ColorPicker.Background = selectedColor;
return;
}
var isColorIdentical = ((SolidColorBrush)ColorPicker.Background).Color == selectedColor.Color;
ColorPicker.Background = isColorIdentical
? _originalColor
: selectedColor;
#endregion
}
private SolidColorBrush SelectedColor(string value)
{
#region UserControlSyntax
//var selectedColor = (Color)ColorConverter.ConvertFromString(value);
#endregion
#region PropertyElementSyntax
var selectedColor = (Color)ColorConverter.ConvertFromString((string)ColorPicker.SelectedItem);
#endregion
return new SolidColorBrush(selectedColor);
}
问题是在no- UserControl
场景中, DataContext
是在初始化命令对象之前设置的。
WPF有一个健壮的绑定系统,但它通常依赖于属性更改通知,通过INotifyPropertyChanged
。 只要您获得正确的操作顺序,某些方案就可以在没有它的情况下工作。 但是,如果没有属性更改通知,如果您错过了向WPF提供某些属性值的机会窗口,那么以后就不会再尝试了。
使用UserControl
时,在设置ChangeColorCommand
属性后,将初始化UserControl
的绑定。 这只是WPF如何初始化UI树中各种对象的工件。 但这意味着,当UserControl
的绑定查看ChangeColorCommand
属性时,它具有您想要的值。
另一方面,当您将StackPanel
显式放入窗口的XAML时,在设置WPF的属性以查看它时为时已太晚。 它已在InitializeComponent()
调用期间解析了这些绑定。 稍后设置属性无效。
根据您现有的代码,有几种方法可以解决这个问题:
DataContext = this;
的赋值DataContext = this;
在调用InitializeCommand()
。 更新DataContext
需要WPF更新所有依赖绑定,因此在InitializeCommand()
调用之后执行此操作可确保该属性具有所需的值。 MainWindow
类中实现INotifyPropertyChanged
,并在设置时为ChangeColorCommand
属性引发PropertyChanged
事件。 这将让WPF知道值已更改,并且应该重新评估依赖于它的任何绑定。 所有这些,我再往前走一步:
INotifyPropertyChanged
和ChangeColorCommand
实现适当的视图模型对象,并将其用作数据上下文。 使UI对象具有双重功能,因为UI和属性绑定源(即视图模型的工作)不适合普通的WPF模型,牺牲了MVVM通常会提供的好处,当然还会引入这种奇怪的时机不清楚为什么属性绑定没有按预期工作的事情。
好的,从技术上讲,你可以采用第四种方法,即在InitializeCommand()
之前调用InitializeComponent()
。 主要问题是,目前它依赖于直接检索UI对象属性的值,并且该UI对象在调用InitializeComponent()
之后才会存在。
这让我回到了上面的#3选项。 事实上,您不应该直接访问UI对象属性。 这应该是视图模型中的另一个属性,您应该更直接地选择初始颜色应该是什么,而不仅仅是在启动时从UI中抓取它。
我承认,这里有一些摆设空间,但你应该尽量保持你的视图模型和UI代码彼此脱节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.