突出显示ListViewItem仅按OnMouseOver和Modifier键

时间:2015-03-09 02:01:58

标签: c# wpf

我正在尝试向ListView的ItemContainerStyle添加一个样式,以便当我的鼠标移过该行并按下一个修改键时(例如Alt),该行只会以某种颜色突出显示。 MouseOver部分是直接的,但不确定如何处理样式中的按键部分。

XAML突出显示OnMouseOver:

<Style x:Key="CustomListViewItemStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Grid>
                    <Border x:Name="ListViewItemBorder" BorderBrush="Black" BorderThickness="2" />
                    <GridViewRowPresenter Columns="{TemplateBinding GridView.ColumnCollection}" Content="{TemplateBinding Content}" />
                </Grid>
              <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                  <Setter TargetName="ListViewItemBorder" Property="BorderBrush" Value="Red"/>
                  <Setter TargetName="ListViewItemBorder" Property="BorderThickness" Value="4"/>
                </Trigger>
              </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

1 个答案:

答案 0 :(得分:0)

我的解决方法是使用EventTriggerBase<T>中的自定义System.Windows.Interactivity

public class MyMouseMoveEvenTrigger : EventTriggerBase<ListView>
{
    public ModifierKeys Modifier
    {
        get { return (ModifierKeys) GetValue(ModifierProperty); }
        set { SetValue(ModifierProperty, value); }
    }

    public static readonly DependencyProperty ModifierProperty =
        DependencyProperty.Register("Modifier", typeof (ModifierKeys), typeof (MyMouseMoveEvenTrigger), new PropertyMetadata(ModifierKeys.None));

    public Key Key
    {
        get { return (Key) GetValue(KeyProperty); }
        set { SetValue(KeyProperty, value); }
    }

    public static readonly DependencyProperty KeyProperty =
        DependencyProperty.Register("Key", typeof (Key), typeof (MyMouseMoveEvenTrigger), new PropertyMetadata(Key.None));

    private bool _matchPredicate;

    private ListView ListView
    {
        get { return AssociatedObject as ListView; }
    }

    protected override void OnAttached()
    {
        Keyboard.AddPreviewKeyDownHandler(ListView, PreviewKeyDownHandler);
        Keyboard.AddKeyUpHandler(ListView, KeyUpHandler);

        base.OnAttached();
    }

    private void PreviewKeyDownHandler(object s, KeyEventArgs e)
    {
        var modifierOk = Equals(Modifier, DependencyProperty.UnsetValue) || Modifier == ModifierKeys.None || Keyboard.Modifiers == Modifier;
        var keyOk = Equals(Key, DependencyProperty.UnsetValue) || Key == Key.None || Keyboard.IsKeyDown(Key);

        _matchPredicate = modifierOk && keyOk;
        e.Handled = _matchPredicate;

        RefreshItems();
    }

    private void KeyUpHandler(object s, KeyEventArgs e)
    {
        _matchPredicate =
            (Equals(Modifier, DependencyProperty.UnsetValue) || Modifier == ModifierKeys.None)
            &&
            (Equals(Key, DependencyProperty.UnsetValue) || Key == Key.None);

        RefreshItems();
    }

    protected override void OnDetaching()
    {
        Keyboard.RemoveKeyDownHandler(ListView, PreviewKeyDownHandler);
        Keyboard.RemoveKeyUpHandler(ListView, KeyUpHandler);

        base.OnDetaching();
    }

    protected override void OnEvent(EventArgs eventArgs)
    {
        Keyboard.Focus(ListView);

        var modifierOk = Equals(Modifier, DependencyProperty.UnsetValue) || Modifier == ModifierKeys.None || Keyboard.Modifiers == Modifier;
        var keyOk = Equals(Key, DependencyProperty.UnsetValue) || Key == Key.None || Keyboard.IsKeyDown(Key);

        _matchPredicate = modifierOk && keyOk;

        RefreshItems();
    }

    private void RefreshItems()
    {
        foreach (ListViewItem lvi in ListView.Items)
        {
            lvi.Tag = _matchPredicate && lvi.IsMouseOver ? "Yes" : null;
        }
    }

    protected override string GetEventName()
    {
        return "MouseMove";
    }
}

由于MyMouseMoveEvenTrigger使用Tag属性(在谓词匹配时设置字符串“是”),我们需要更改ControlTemplate.Triggers

...
<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="False">
        <Setter Property="Tag" Value=""/>
    </Trigger>
    <Trigger Property="Tag" Value="Yes">
        <Setter TargetName="Border" Property="BorderBrush" Value="Red"/>
        <Setter TargetName="Border" Property="BorderThickness" Value="4"/>
    </Trigger>
</ControlTemplate.Triggers>
...

最后,将自定义触发器包含到ListView对象中。该示例使用键 C 和修饰符 Alt

<ListView>
    <i:Interaction.Triggers>
        <wpfCalc:MyMouseMoveEvenTrigger Modifier="Alt" Key="C"/>
    </i:Interaction.Triggers>
...
</ListView>

我希望它有所帮助。