闪烁来自 ViewModel 的图像

Blink an image from ViewModel

我想在用户单击按钮时向他们提供一些反馈,这会启动一个可能很长的请求。

我将 WPF 与 mvvm 一起使用,我想开始使单击的图像闪烁。

这是 XAML 代码:

<Button Style="{DynamicResource BtnToolBar}" Command="{Binding refreshAll}">
     <Image x:Name="imgUpd" Style="{DynamicResource ImageStyleUpd}" ToolTip="{StaticResource UpdateData}"/>
</Button>

我想要这样的东西:

isBlinking="{Binding isBlinking}"

它存在吗?如何从 ViewModel 制作闪烁的图像?可能吗?

编辑:我用我找到的 solution 写了这篇文章。

您可以使用 viewmodel 开始闪烁。做你想做的事,你需要:

  • 向您的 ImageStyleUpd 样式添加新 DataTrigger
  • 将它绑定到你的 isBlinking 属性 和 "True" 值
  • 在触发器中,您可以根据需要为图像设置动画(例如,更改图像的不透明度)

例子

<Style x:Key="ImageStyleUpd" TargetType="{x:Type Image}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsBlinking}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard x:Name="blinking">
                    <Storyboard RepeatBehavior="Forever">
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" AutoReverse="True"
                                         To="0.5" Duration="0:0:0.5">
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <StopStoryboard BeginStoryboardName="blinking"/>
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

希望对你有帮助。

闪烁通常是视图中的动画,在视图模型中可以是started/stopped by IsBlinking 属性。您可以通过改变 DropShadowEffect(平滑闪烁)或通过简单切换两个刷子来实现闪烁效果:

<DataTrigger Binding="{Binding IsBlinking}" Value="True">
    <DataTrigger.EnterActions>
        <BeginStoryboard x:Name="blinking">
            <Storyboard RepeatBehavior="Forever">
                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="item"
                                               Storyboard.TargetProperty="Background">
                    <DiscreteObjectKeyFrame Value="Red" KeyTime="0:0:0"/>
                    <DiscreteObjectKeyFrame Value="White" KeyTime="0:0:0.3"/>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.5"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="blinking"/>
    </DataTrigger.ExitActions>
</DataTrigger>

item - 是您想要制作动画的 Background(或 Foreground/Fill 等)的视觉效果。

<!-- to example path, use Storyboard.TargetProperty="Fill" -->
<Path x:Name="item" Fill="SomeDefaultNonBlinkingBrush" ... />

我喜欢在行为中做这种事情,它是可重复使用的,你可以在任何 UIElement.

上设置这个 属性
public static class FlickrBehavior
{
    #region IsFlickering

    public static bool GetIsFlickering(UIElement element)
    {
        return (bool)element.GetValue(IsFlickeringProperty);
    }

    public static void SetIsFlickering(UIElement element, bool value)
    {
        element.SetValue(IsFlickeringProperty, value);
    }

    public static readonly DependencyProperty IsFlickeringProperty =
        DependencyProperty.RegisterAttached("IsFlickering", typeof(bool), typeof(FlickrBehavior), new UIPropertyMetadata(false, OnIsFlickeringChanged));

    static void OnIsFlickeringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
            StartAnimation(d as UIElement);
        else
            StopAnimation(d as UIElement);
    }

    private static void StartAnimation(UIElement element)
    {
        DoubleAnimation da = new DoubleAnimation();
        da.From = 1;
        da.To = 0;
        da.Duration = new Duration(TimeSpan.FromSeconds(2));
        da.AutoReverse = true;
        da.RepeatBehavior = RepeatBehavior.Forever;
        element.BeginAnimation(UIElement.OpacityProperty, da);
    }

    private static void StopAnimation(UIElement element)
    {
        element.BeginAnimation(UIElement.OpacityProperty, null);
    }

    #endregion
}

与@Novitchi 的回答类似,我也想创建一个带有附加 属性 的行为。但我会将行为附加到 mouse click:

所以你可以创建你的行为如下:

public static class BlinkingBehaviour
{
    public static bool GetIsBlinkingWhenClick(UIElement element)
    {
        return (bool)element.GetValue(IsBlinkingWhenClickProperty);
    }

    public static void SetIsBlinkingWhenClick(UIElement element, bool value)
    {
        element.SetValue(IsBlinkingWhenClickProperty, value);
    }

    public static readonly DependencyProperty IsBlinkingWhenClickProperty =
        DependencyProperty.RegisterAttached(
           "IsBlinkingWhenClick", 
           typeof(bool), 
           typeof(BlinkingBehaviour), 
           new FrameworkPropertyMetadata(false, OnIsBlinkingWhenClickChanged));

    static void OnIsBlinkingWhenClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
        {
            (d as UIElement).PreviewMouseLeftButtonDown -= BlinkingWhenClickBehavior_PreviewMouseLeftButtonDown;
            (d as UIElement).PreviewMouseLeftButtonDown += BlinkingWhenClickBehavior_PreviewMouseLeftButtonDown;
        }
        else
        {
            (d as UIElement).PreviewMouseLeftButtonDown -= BlinkingWhenClickBehavior_PreviewMouseLeftButtonDown;
        }
    }

    static void BlinkingWhenClickBehavior_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DoubleAnimation blink = new DoubleAnimation() { 
                        To = 1, 
                        From = 0, 
                        Duration = TimeSpan.FromMilliseconds(200) };
        (sender as UIElement).BeginAnimation(UIElement.OpacityProperty, blink);
    }
}

然后在您的 XAML 中,您可以将其附加到您的 image:

<Window x:Class="YourNameSpace.YourWindowClass"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:YourNameSpace"    
    <Button ...>
        <Image local:BlinkingBehaviour.IsBlinkingWhenClick="True"  .../>
    </Button>
</Window>