I want to begin a storyboard, every time my Image source changes. I have implemented INotifyPropertyChanged.
Can anyone help me achieve this?
Thanks,
<Image Name="pic" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding ElementName=uc, Path=Image}">
<Image.Resources>
<Storyboard x:Key="picStory" x:Name="picStory">
<DoubleAnimation
Storyboard.TargetProperty="(Image.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"
From="0" To="20" Duration="0:0:0.7" />
<DoubleAnimation Storyboard.TargetProperty="(Image.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)" From="100" To="0" Duration="0:0:0.7" />
</Storyboard>
</Image.Resources>
<Image.Style>
<Style TargetType="{x:Type Image}" BasedOn="{StaticResource {x:Type Image}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Source}">开发者_Go百科;
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource picStory}"/>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
<Image.RenderTransform>
<TransformGroup>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
Code bound to "uc":
private BitmapImage image;
public BitmapImage Image
{
get { return image; }
set
{
image = value;
OnPropertyChanged("Image");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
you can achieve this in another simple way by building a very basic custom control, which inherits from Image.
Here the code for "MyImage":
public class MyImage : Image
{
public static readonly RoutedEvent ImageUpdatedEvent =
EventManager.RegisterRoutedEvent("ImageUpdated", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyImage));
public event RoutedEventHandler ImageUpdated
{
add { this.AddHandler(ImageUpdatedEvent, value); }
remove { this.RemoveHandler(ImageUpdatedEvent, value); }
}
public static readonly DependencyProperty MyImageSourceProperty = DependencyProperty.Register(
"MyImageSource",
typeof(ImageSource),
typeof(MyImage),
new PropertyMetadata(null, new PropertyChangedCallback(OnMyImageSourceChanged)));
public ImageSource MyImageSource
{
get { return (ImageSource)GetValue(MyImageSourceProperty); }
set
{
Source = value;
SetValue(MyImageSourceProperty, value);
}
}
private static void OnMyImageSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
MyImage img = obj as MyImage;
img.Source = args.NewValue as ImageSource;
img.RaiseEvent(new RoutedEventArgs(ImageUpdatedEvent));
}
}
The MyImage control has it's own image source property and an own routed event called "ImageUpdated", which will later cause the storyboard to be triggerd. I have simplified your image code:
<Button Click="Button_Click" Grid.Row="0">Set Image through view model</Button>
<local:MyImage Grid.Row="1" x:Name="pic" MyImageSource="{Binding MySource}">
<Image.Triggers>
<EventTrigger RoutedEvent="local:MyImage.ImageUpdated">
<BeginStoryboard >
<Storyboard >
<DoubleAnimation Storyboard.TargetProperty="(Image.Opacity)" From="0" To="1" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</local:MyImage>
The button sets a new value for the image source property of the bound viewmodel, which implements INotifyPropertyChanged:
private void Button_Click(object sender, RoutedEventArgs e)
{
int randomValue = new Random(DateTime.Now.Second).Next(0, 2);
if (randomValue == 0)
{
_viewModel.MySource = new BitmapImage(new Uri(@"test.bmp", UriKind.Relative));
}
else
{
_viewModel.MySource = new BitmapImage(new Uri(@"test2.bmp", UriKind.Relative));
}
}
The setter in the viewmodel updates the MyImage with property changed pattern:
public ImageSource MySource
{
get { return _mySource; }
set
{
_mySource = value;
RaisePropertyChanged("MySource");
}
}
In my example, the opacity property is animated.
Hope this was helpful
Jan
You have no Value-tag defined in your DataTrigger.
The DataTrigger is listening to updates to find the value you define in the Value-Tag - since you haven't set it - it defaults to null (and I'm guessing your image is never null).
If you want it to fire everytime it changes - just put a valueconverter in the Binding tag that always returns True and set Value="True".
精彩评论