【问题标题】:Silverlight: Can an event from one usercontrol begin an animation on a different usercontrol and/or the containing controlSilverlight:来自一个用户控件的事件是否可以在不同的用户控件和/或包含控件上开始动画
【发布时间】:2011-10-20 21:19:49
【问题描述】:

我在 Silverlight 中有三个 UserControl。

UCOutside 包含两个名为 UCInside1 和 UCInside2 的用户控件。

包含用户控件

<!-- UCOutside --> 
<UserControl.Resources>
    <Storyboard x:Name="OutsideBoard">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="LayoutRoot">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="45"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</UserControl.Resources>

<Grid x:Name="LayoutRoot">
    <Grid.Projection>
        <PlaneProjection/>
    </Grid.Projection>
    <local:UCInside1 Margin="39,35,266,173"/>
    <local:UCInside2 HorizontalAlignment="Right" Margin="0,234,26,30" />
</Grid>

里面的第一个 UserControl

<!-- UCInside1 -->
<UserControl.Resources>
    <Storyboard x:Name="ImageFade">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="myImage">
            <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.2"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image x:Name="myImage" Margin="0" Source="/OtherImage.png" Stretch="Fill" Width="312" Height="250" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>

里面的第二个UserControl

<!-- UCInside2 -->
<UserControl.Resources>
    <Storyboard x:Name="ButtonFade">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="image1">
            <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" HorizontalAlignment="Left" Height="195" VerticalAlignment="Top" Width="218">
    <Button Content="Button" HorizontalAlignment="Right" Margin="0,0,25,51" VerticalAlignment="Bottom" Width="75" Click="ClickButton"/>
    <Image x:Name="image1" HorizontalAlignment="Left" Margin="41,32,0,70" Source="/Whatever.png" Stretch="Fill" Width="47"/>
</Grid>

您会注意到 Button 上的 ClickButton 事件。您还会注意到所有用户控件中都指定了简单的故事板。

问题是如何让所有三个动画都通过点击事件开始?是否可以通过 XAML 或使用 Blend 将其全部绑定?如果不是,在c#代码中是如何完成的?

【问题讨论】:

    标签: c# wpf silverlight xaml visualstatemanager


    【解决方案1】:

    我想说解决这个问题的一种非常简单有效的方法是使用 INotifyPropertyChanged 接口来使用观察者模式。

    让触发初始事件的容器成为可观察部分,让其他两个观察它。因此,每当可观察容器执行某些操作(例如触发点击事件)时,其他容器都会收到通知并做出相应的反应。

    一旦您的 OutsideContainer 类是可观察的,请执行以下两个步骤:

    1. 在 OutsideButton 类中,在适当的位置触发 PropertyChanged 事件(例如,发生“超级”点击的位置。

    2. 在 ImageFade 和 ButtonFace 类中聊天 PropertyChanged 事件并执行某些操作(例如,让他们触发自己的点击事件)。

    尝试以下方法:

    在代码隐藏文件 OutsideBoard.cs 中实现 INotifyPropertyChanged 接口以使其可观察:

    class OutsideBoard : INotifyPropertyChanged {
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void FirePropertyChanged (string property) {
    
            if (PropertyChanged != null) {
    
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    
        // the click- EventHandler of your UserControl
        public event Click_EventHandler (object sender, RoutedEventArgs e) {
    
            // your clicking code of your UserControl
    
            FirePropertyChanged("SuperClick");
        }
    
    
        // rest of the code inhere ...
    }
    

    现在每个想要观察 OutsideBorder 类的类都必须在该类上实现一个 EventHandler:

    在 ButtonFade 和 ImageFade 类中编写如下内容:

    outsideBorder.PropertyChanged += PropertyEventChangeHandler(MyClickHandling);
    
    public void MyClickHandling (object sender, PropertyChangeEventArgs e) {
    
         // do something
    }
    

    因此,每当 OutsideBoard 类触发 PropertyChanged 事件时,所有观察者都会通过调用其 MyClickHandling - 方法得到通知。

    希望对你有所帮助。

    【讨论】:

    • 马克,谢谢。使用 INotifyPropertyChanged 是如何做到这一点,但不是你上面显示的那样。我所做的是让子控件(即实际包含按钮并随后接收其事件的那个)实现 INotifyPropertyChanged 接口。当一个人这样做时,所有包含的用户控件所要做的就是订阅 PropertyChanged 事件,如果还需要通知另一个子控件,那么另一个子控件可以实现并公开 PropertyChanged 的​​处理程序,并且包含的​​ UserControl 可以订阅另一个子控件参加活动。
    【解决方案2】:

    再次经历之后,我发现可能有一个更简单的解决方案:)

    如果您想在您的 OutsideBoard 类中对另一个类的单击事件做出反应 - 只需捕获该特定事件 :)

    所以在你的“孩子”的代码隐藏中简单地写(假设你的 OutsideBorder 类是 outsideBorder

    outsideBorder.Click += MouseEventHandler(MyClickHandler);
    
    public void MyClickHandler (object sender, MouseEventArgs e) {
    
        // do something to react on the click appeared in the OutsideBoard class.
    }
    

    因此,OutsideBoard 的点击事件将像它本身一样被聊天(没有您的干扰)您所做的就是简单地向该点击触发控件添加额外的 EventHandler :)

    【讨论】:

    • 我想我试图避免的是孩子们知道父母的详细信息。该事件发生在孩子身上,但我试图弄清楚如何连接它以通知父母并通知其他用户控件,这是一个“兄弟”,因为缺少更好的术语。
    猜你喜欢
    • 1970-01-01
    • 2016-05-12
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2013-04-23
    • 1970-01-01
    • 2012-08-12
    相关资源
    最近更新 更多