gpt4 book ai didi

c# - KeyBinding 用作 UserControl,但在 XAML 中使用属性元素语法时不起作用

转载 作者:行者123 更新时间:2023-11-30 17:26:12 25 4
gpt4 key购买 nike

如标题所述,在使用属性元素语法时,我无法使 KeyBinding 工作。我所说的工作是指使用 Ctrl+Del 组合键来更改列表框的背景颜色。可以使用组合键或单击按钮,两者都会调用命令,但永远不会调用命令。在 Debug模式下设置断点时,它永远不会遇到。

我关注了 InputBinding Class example从文档中获取,并且只能在使用 UserControl 时让 KeyBinding 工作,并且想了解为什么,以及什么 我做错了。

下面是当使用属性元素语法声明的代码不起作用时的 MVCE。注释掉的是 UserControl 的一行,它封装了 StackPanel 并允许 KeyBinding 工作。取决于在 MainWindow.xaml.cs 的代码后面注释掉每个 PropertyElementSyntax 区域并取消注释每个 UserControlSyntax 区域。

主窗口.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);
}

最佳答案

问题在于,在无UserControl 的情况下,DataContext 是在命令对象初始化之前设置的。

WPF 具有强大的绑定(bind)系统,但它通常依赖于通过 INotifyPropertyChanged 进行的属性更改通知。只要您获得正确的操作顺序,某些场景在没有它的情况下也可以工作。但是,如果没有属性更改通知,如果您错过了向 WPF 提供某些属性值的机会窗口,它不会稍后再试。

当您使用 UserControl 时,UserControl 的绑定(bind)初始化发生在您设置 ChangeColorCommand 属性之后。这只是 WPF 如何初始化 UI 树中的各种对象的产物。但这意味着当 UserControl 的绑定(bind)查看 ChangeColorCommand 属性时,它具有您想要的值。

另一方面,当您将 StackPanel 显式放入窗口的 XAML 中时,为 WPF 设置属性以查看它时为时已晚。它已经在 InitializeComponent() 调用期间解析了这些绑定(bind)。稍后设置该属性无效。

根据您现在拥有的代码,您可以通过多种方式解决该问题:

  1. 最简单的方法是将 DataContext = this; 的赋值移动到调用 InitializeCommand() 之后。更新 DataContext 也需要 WPF 更新所有依赖绑定(bind),因此在 InitializeCommand() 调用之后执行此操作可确保属性具有您想要的值。
  2. MainWindow 类中实现 INotifyPropertyChanged,并在设置时引发 ChangeColorCommand 属性的 PropertyChanged 事件它。这将使 WPF 知道该值已更改,并且它应该重新评估依赖于它的任何绑定(bind)。

综上所述,我会更进一步:

  1. 使用 INotifyPropertyChangedChangeColorCommand 实现适当的 View 模型对象,并使用 that 作为数据上下文。让您的 UI 对象执行双重任务,因为 UI 和属性绑定(bind)源(即 View 模型的工作)不适合普通的 WPF 模型,牺牲了 MVVM 通常提供的好处,当然也引入了这种奇怪的计时属性绑定(bind)未按预期工作的原因并不明显。


好的,从技术上讲,您可以采用第四种方法,即在 InitializeComponent() 之前调用 InitializeCommand()。其主要问题是,目前,它依赖于直接检索 UI 对象的属性值,并且该 UI 对象只有在调用 InitializeComponent() 之后才会存在。

这让我回到上面的 #3 选项。事实上,您不应该直接访问 UI 对象属性。这应该是你的 View 模型中的另一个属性,你应该更直接地选择初始颜色应该是什么,而不是在启动时从 UI 中获取它。

我承认,这里的设计有一些回旋余地,但您应该尽量让 View 模型和 UI 代码彼此分离。

关于c# - KeyBinding 用作 UserControl,但在 XAML 中使用属性元素语法时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57103538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com