【问题标题】:WPF - Bind Visibility to state of keyWPF - 将可见性绑定到键状态
【发布时间】:2013-11-04 09:20:30
【问题描述】:

如果可能通过转换器,我需要将 WPF UserControl 上控件的可见性绑定到 Alt 键的状态。仅当按下 ALT 键时,该按钮才可见,该解决方案不应集成到代码隐藏文件中,因为我正在使用 PRISM/Unity 以严格的 MVVM 模式工作。

一个完美的解决方案包括编写一个新的转换器,该转换器能够将键盘键的状态转换为用户控件的 Visiblity 属性,但我在转换器方面经验不足,无法想出一个自己解决。

【问题讨论】:

  • 将输入绑定与转换器一起使用。我会发布一个例子
  • @Omribitan 那太好了!

标签: c# .net wpf mvvm ivalueconverter


【解决方案1】:

这是一个完整的例子

Xaml

<Window x:Class="Playground.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Playground"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        Title="MainWindow" Height="350" Width="525">
    <Window.InputBindings>
        <KeyBinding Modifiers="Alt" Key="LeftAlt" Command="{Binding AltPressedCommand}" />
    </Window.InputBindings>
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="boolToVisibilityConverter"/>
    </Window.Resources>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewKeyUp">
            <i:InvokeCommandAction Command="{Binding AltUnpressedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Button Content="My Button" Visibility="{Binding IsAltPressed, Converter={StaticResource boolToVisibilityConverter}}"/>
    </Grid>
</Window>

视图模型

public class MainWindowViewModel : NotificationObject
{
    public MainWindowViewModel()
    {
        AltPressedCommand = new DelegateCommand(() => IsAltPressed = true);
        AltUnpressedCommand = new DelegateCommand(() => IsAltPressed = false);
    }

    public DelegateCommand AltPressedCommand { get; set; }

    public DelegateCommand AltUnpressedCommand { get; set; }

    private bool _IsAltPressed;
    public bool IsAltPressed
    {
        get { return _IsAltPressed; }
        set
        {
            if (value != _IsAltPressed)
            {
                _IsAltPressed = value;
                RaisePropertyChanged("IsAltPressed");
            }
        }
    }
}

说明

控件的可见性通过BooleanToVisibilityConverter 绑定到一个布尔属性。 然后我使用两个命令。一个在使用 KeyBinding 按下 Alt 键时触发,第二个在键向上时触发。当您应该添加键时,我忽略了对 Alt 键的检查。如果您想纯粹使用 MVVM,这可能会变得很棘手,因为您需要向命令发送一个参数来说明正在按下的键。

编辑

我使用以下行为从 PreviewKeyUp 事件中传递 key 参数

public class PreviewKeyUpBehavior : Behavior<UIElement>
{
    #region Properties

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(PeviewKeyUpBehavior));

    #endregion

    #region Methods

    protected override void OnAttached()
    {
        AssociatedObject.PreviewKeyUp += OnPreviewKeyUp;
        base.OnAttached();
    }

    private void OnPreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
    {
        if (Command == null) return;


        // Execute command and send the key as the command parameter
        Command.Execute(e.Key == Key.System ? e.SystemKey : e.Key);
    } 

    #endregion
}

这将在PreviewKeyUp 被触发时引发绑定命令并将密钥作为命令参数发送。然后我将 View 和 ViewModel 中的代码修改如下:

<!-- Used behaviors instead of triggers -->
<i:Interaction.Behaviors>
    <local:PreviewKeyUpBehavior Command="{Binding KeyUnpressedCommand}"/>
</i:Interaction.Behaviors>

将命令更改为采用可为空的键参数

public DelegateCommand<Key?> KeyUnpressedCommand { get; set; }

并实现了

KeyUnpressedCommand = new DelegateCommand<Key?>(key => 
{
    if (key == Key.LeftAlt)
        IsAltPressed = false;
});

希望对你有帮助

【讨论】:

  • 这看起来是一个很好的解决方案,但我仍然必须更改视图的视图模型文件,这通常不是我想要的。我有轻微的感觉,但不会有其他方法......如果我的假设被证明是正确的,我会将你的答案标记为正确。
  • 这通常来自 Blend 命名空间...你安装了 blend 吗?
  • @Klausklapper 您需要添加对System.Windows.Interactivity 的引用。就像@Noctis 所说,它通常带有Blend 安装,但如果你没有安装它,你可以从Blend SDK 获得它。
  • 好吧,在其他参考资料上做得过分了。我已经安装了 blend ,但我不太确定这个解决方案是否会满足我们的代码 QA :/
  • @Omribitan 的新更新使我的答案变得多余,但同样,有时背后的代码是正确的答案:)(去过那里,做过,我知道你的感受)。无论如何,Omri 做得很好。
猜你喜欢
  • 2012-05-23
  • 2018-12-28
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多