延迟取消选择ListBoxItem

时间:2019-06-12 10:47:27

标签: c# wpf xaml properties triggers

我想实现一种效果,其中ListBoxItem被选中(突出显示)几秒钟,然后被取消选中。试图实现具有淡入淡出效果的简单控件高光,但是为了使事情正常进行,我需要相应地更改属性。

我有一个IsSelected属性绑定到我的视图模型属性:

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Style>

我的财产看起来像这样:

public bool IsSelected
{
    get => _isSelected;
    set
    {
        // Update value
        _isSelected = value;

        // Raise property changed
        OnPropertyChanged(nameof(IsSelected));
    }
}

我尝试使用延迟绑定:

<ControlTemplate TargetType="{x:Type ListBoxItem}">
    <ControlTemplate.Triggers>
        <!--  Deselect after 5 seconds  -->
        <DataTrigger Binding="{Binding IsSelected, Delay=5000}" Value="True">
            <Setter Property="IsSelected" Value="False" />
        </DataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

我也尝试使用情节提要:

<ControlTemplate TargetType="{x:Type ListBoxItem}">
    <ControlTemplate.Triggers>
        <!--  Deselect after 5 seconds  -->
        <DataTrigger Binding="{Binding IsSelected}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
                            <DiscreteBooleanKeyFrame KeyTime="00:00:05" Value="False" />
                        </BooleanAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

不幸的是,以上方法似乎都无法更新我的IsSelected属性,并且ListBoxItem仍处于选中状态并突出显示。

我希望以XAML(或扩展名),MVVM样式,没有任何背后的代码且没有浪费的计时器来完成此操作-这可能吗? 如果是这样,我该如何正确地延迟选择ListBoxItem

1 个答案:

答案 0 :(得分:2)

以下是一个附加行为的示例,该行为应或多或少地执行您想要的操作:

public class DeselectBehavior
{
    public static bool GetIsEnabled(ListBox listBox)
    {
        return (bool)listBox.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(ListBox listBox, bool value)
    {
        listBox.SetValue(IsEnabledProperty, value);
    }

    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached(
        "IsEnabled",
        typeof(bool),
        typeof(DeselectBehavior),
        new UIPropertyMetadata(false, OnChanged));

    private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ListBox listBox = d as ListBox;
        if((bool)e.NewValue)
        {
            listBox.AddHandler(ListBoxItem.SelectedEvent, (RoutedEventHandler)OnListBoxItemSelected, true);
        }
        else
        {
            listBox.RemoveHandler(ListBoxItem.SelectedEvent, (RoutedEventHandler)OnListBoxItemSelected);
        }
    }

    private static async void OnListBoxItemSelected(object sender, RoutedEventArgs e)
    {
        await Task.Delay(2000);
        ListBoxItem listBoxItem = e.OriginalSource as ListBoxItem;
        if (listBoxItem != null)
            listBoxItem.IsSelected = false;
    }
}

XAML:

    <ListBox ... local:DeselectBehavior.IsEnabled="True">
    ...