我正在开发一个使用MVVM,KeyBinding和ICommand的项目。
我在同一窗口上有多个嵌套视图(UserControls),其中许多使用相同的键绑定“ Ctrl + S”来运行SaveCommand
。
与视图关联的ViewModel具有IsSaveCommandAvailable
属性,该属性可以判断该视图模型中是否有SaveCommand
。
在我的情况下,只有“根”视图才能通过按Ctrl + S来启动SaveCommand
,嵌套的视图必须忽略按键并让其冒泡到根视图,完成所有保存工作。
我搜寻了一个解决方案,但发现我可以使用ICommand.CanExecute
返回false并避免运行KeyBinding。
但是此解决方案不符合我的需要,因为如果我在子视图上按Ctrl + S,则其SaveCommand
CanExecute返回false,并且击键丢失。
有没有办法使按键击中气泡,直到可以运行KeyBinding?
答案 0 :(得分:1)
我找到的解决方案是在KeyBinding的IValueConverter
属性上使用Key
,将布尔值转换为作为CommandParameter传递的键,如果值是false
,返回Key.None
:
public class BooleanToKeyConverter : IValueConverter
{
/// <summary>
/// Key to use when the value is false
/// </summary>
public Key FalseKey { get; set; } = Key.None;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool flag && flag && parameter != null && parameter != DependencyProperty.UnsetValue)
{
if (parameter is Key key)
{
return key;
}
else if (Enum.TryParse<Key>(parameter.ToString(), out var parsedKey))
{
return parsedKey;
}
}
return this.FalseKey;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
在资源文件中(例如:App.xaml):
<conv:BooleanToKeyConverter x:Key="boolToKey"/>
其中“ conv”是您的本地名称空间。
然后,在键绑定中:
<KeyBinding Command="{Binding Path=SaveCommand}"
Key="{Binding Path=IsSaveCommandAvailable, Converter={StaticResource boolToKey}, ConverterParameter=S}"
Modifiers="Ctrl"/>
答案 1 :(得分:1)
如果您希望保留Key
属性不变(且可绑定),则可以派生KeyBinding
并添加IsEnabled
依赖属性,同时覆盖Gesture
:>
public override InputGesture Gesture
{
get
{
return IsEnabled ? base.Gesture as KeyGesture : new KeyGesture(Key.None);
}
set
{
base.Gesture = value;
}
}
// IsEnabled dependency property changed callback
private static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as MyKeyBinding)?.WritePostscript(); // raise Gesture changed
}
不要忘记通知UI Gesture
中的IsEnabled
已使用WritePostscript()
更改了回调并覆盖了CreateInstanceCore
。
用法示例:
<utils:MyKeyBinding
Command="{Binding SaveCommand}"
Key="{Binding KeyBindings.SaveKey}"
Modifiers="{Binding KeyBindings.SaveModifiers}"
IsEnabled="{Binding IsSaveCommandAvailable}"/>