WPF故事板只在第一次调用时触发

本文关键字:调用 第一次 故事 WPF | 更新日期: 2023-09-27 17:54:39

我一直试图在控件中显示一条消息,当我收到一条消息说我已发布的更新已成功接收时,该消息仅出现几秒钟。

我有一个类实现INotifyPropertyChanged如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Wpf.GUI.Views
{
public class AlertBarStatus : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public event RoutedEventHandler VisibleChanged;
    private bool _visible ;
    private bool _success ;
    public AlertBarStatus():this (false,false)
    {
    }

    public AlertBarStatus(bool visible, bool success)
    {
        _visible = visible;
        _success = success;
    }

    public bool Visible
    {
        get { return _visible; }
        set
        {
            _visible = value;
            OnPropertyChanged("Visible");
            if(VisibleChanged != null)
            {
                VisibleChanged(this, null);
            }
        }
    }
    public bool Success
    {
        get { return _success; }
        set
        {
            _success = value;
            OnPropertyChanged("Success");
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
}

我有xaml,它包含如下控件:

<UserControl x:Class="Wpf.GUI.AlertBarControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         DataContext="{Binding RelativeSource={RelativeSource Self}}"
         >
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Border x:Name="alertStatusBorder" Height="50" Visibility="Collapsed" Opacity="0" HorizontalAlignment="Stretch" >
        <Border.Style>
            <Style TargetType="Border">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding AlertBarStatus.Success}" Value="True">
                        <Setter Property="Background" Value="{StaticResource EnabledBorderBackground}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding AlertBarStatus.Success}" Value="False">
                        <Setter Property="Background" Value="{StaticResource DisabledBorderBackground}" />
                    </DataTrigger>
                    <DataTrigger x:Name="VisibilityTrigger" Binding="{Binding AlertBarStatus.Visible}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard x:Name="VisibilityStoryboard">
                                    <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetProperty="(UIElement.Visibility)">
                                        <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                 From="0" To="100" Duration="0:0:5" />
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                 From="100" To="0" Duration="0:0:5" />
                                    <ObjectAnimationUsingKeyFrames Duration="0:0:5" Storyboard.TargetProperty="(UIElement.Visibility)">
                                        <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <StopStoryboard BeginStoryboardName="VisibilityStoryboard"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>

                </Style.Triggers>
            </Style>
        </Border.Style>
        <DockPanel >
            <TextBlock DockPanel.Dock="Left" x:Name="alertStatusText" Grid.Column="0" HorizontalAlignment="Left">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding AlertBarStatus.Success}" Value="True">
                                <Setter Property="Text" Value="Successfully published updates" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding AlertBarStatus.Success}" Value="False">
                                <Setter Property="Text" Value="Failed to publish updates" />
                            </DataTrigger>
                        </Style.Triggers>
                        <Setter Property="FontSize" Value="20"></Setter>
                        <Setter Property="VerticalAlignment" Value="Center"></Setter>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
            <!--<Button Height="20" Width="20" Margin="3" DockPanel.Dock="Right" HorizontalAlignment="Right" 
                    Background="Transparent" BorderBrush="Black"
                    Click="CloseAlertControl_Click">X</Button>-->
        </DockPanel>
    </Border>
</Grid>

名为visbilitytrigger的DataTrigger做了我想要的,但只有当成功值第一次改变时。然后不再调用它。

我知道这个问题有几种不同的答案,但我已经尝试了我能找到的所有解决方案,但到目前为止,它们都不适合我。

为了澄清,可见性属性可以设置为true多次之前,它设置为false,因此我在想,也许这可能是问题,因为我没有设置值为不同的值,但我可以看到OnProperty改变的方法被调用,所以我不希望这是一个问题。

任何帮助在这将是非常感激!

WPF故事板只在第一次调用时触发

最后,我放弃了在xaml中尝试这样做,而是将对象的可见性绑定到底层对象的可见性属性,如下所示。

<Border x:Name="alertStatusBorder" Height="50" Visibility="{Binding Path=AlertBarStatus.Visible, Converter={StaticResource BoolToVis}}">

然后我使用了一个计时器,事件在10秒后触发,将可见性变量设置为false,并禁用定时器,这就像一个魅力。

定时器代码:

Timer _alertBarTimer = new Timer(10000);
_alertBarTimer.Elapsed += _alert_timer_elapsed;
private void _alert_timer_elapsed(object sender, ElapsedEventArgs e)
{
    alertBarControl.AlertBarStatus.Visible = false;
    _alertBarTimer.Enabled = false;
}

设置可见性的代码:

alertBarControl.AlertBarStatus.Visible = true;
_alertBarTimer.Enabled = true;

这可能不是最好的方法,但它肯定不是最坏的,因为我没有直接在代码中设置控件的属性,而是使用绑定到控件的对象。

如果有人有更好的方法,请随时贡献:)