[英]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.