任何数据(绑定)更改时的WPF DataTrigger

3

我想在每次我的图片源更改时开始一个故事板。我已经实现了 INotifyPropertyChanged。

有谁能帮我实现这个目标吗?

谢谢。

<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}">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource picStory}"/>
                        </DataTrigger.EnterActions>                            
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
        <Image.RenderTransform>
            <TransformGroup>
                <RotateTransform/>
                <TranslateTransform/>
            </TransformGroup>
        </Image.RenderTransform>  
    </Image>

与"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));
        }

你能解释一下已经实现INotifyPropertyChanged的情况吗?你没有展示任何代码,并且你的图像源绑定到了某个名为uc的东西,它并不在你展示的XAML中。 - Jay
1
嗨Jay,我已经添加了你要求的代码。然而这不是问题所在,我看到图片在改变,但是故事板没有被激活。 - Arne
2个回答

3

你可以通过构建一个继承自Image的基本自定义控件来以另一种简单的方式实现此操作。

这是"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));
    }
}

MyImage控件有它自己的图像源属性和一个名为“ImageUpdated”的路由事件,这将在后面触发storyboard。我已经简化了您的图像代码:

<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>
设置了绑定的视图模型实现了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));
        }
    }

视图模型中的setter使用属性更改模式更新MyImage:
public ImageSource MySource
    {
        get { return _mySource; }
        set
        {
            _mySource = value;
            RaisePropertyChanged("MySource");
        }
    }

在我的例子中,透明度属性是被动画化的。

希望这有帮助。

Jan


0

您的DataTrigger中未定义Value-tag。

DataTrigger正在侦听更新以查找您在Value-Tag中定义的值 - 因为您尚未设置它 - 它默认为null(我猜测您的图像永远不会为null)。

如果您希望每次更改时都触发它 - 只需在Binding标记中放置一个始终返回True的valueconverter,并设置Value =“True”即可。


你确定这会起作用吗?我尝试了一下,显然如果值不改变触发器就不会触发——也就是说,它只在第一次设置为True时触发,而不是在任何连续的情况下触发... - Rashack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接