闪烁来自 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>
我想在用户单击按钮时向他们提供一些反馈,这会启动一个可能很长的请求。
我将 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>