Отмените выбор ListBoxItem с задержкой - PullRequest
2 голосов
/ 12 июня 2019

Я хочу добиться эффекта, при котором 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 Ответ

2 голосов
/ 12 июня 2019

Вот пример присоединенного поведения, которое должно делать то, что вы хотите, более или менее:

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">
    ...
...