#c# #wpf #silverlight #xaml #visualstatemanager
#c# #wpf #silverlight #xaml #visualstatemanager
Вопрос:
У меня есть три пользовательских элемента управления в Silverlight.
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>
Первый пользовательский элемент управления внутри
<!-- 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>
Второй пользовательский элемент управления внутри
<!-- 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>
Вы заметите, что событие ClickButton на кнопке. Вы также заметите, что во всех пользовательских элементах управления указаны простые раскадровки.
Вопрос в том, как мне запустить все три анимации с помощью события Click? Можно ли все это связать с помощью XAML или с помощью Blend? Если нет, то как это делается в коде c #?
Ответ №1:
я бы сказал, что очень простым и эффективным способом решения этой проблемы было бы использовать интерфейс INotifyPropertyChanged для использования шаблона Observer.
Пусть контейнер, который запускает начальное событие, является наблюдаемой частью, и пусть два других наблюдают за ним. Таким образом, всякий раз, когда наблюдаемый контейнер что-то делает (например, запускает событие щелчка), другие получают информацию и могут реагировать соответствующим образом.
Как только ваш класс OutsideContainer станет наблюдаемым, выполните эти два шага:
-
В классе OutsideButton запускает событие PropertyChanged в соответствующем месте (например, там, где происходит «супер» щелчок.
-
В классах ImageFade и ButtonFace зафиксируйте событие PropertyChanged и сделайте что-нибудь (например, позвольте им запускать свое собственное событие click-event).
Попробуйте следующее:
В коде 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, должен реализовать обработчик событий в этом классе:
Напишите что-то вроде следующего в вашем классе ButtonFade и ImageFade:
outsideBorder.PropertyChanged = PropertyEventChangeHandler(MyClickHandling);
public void MyClickHandling (object sender, PropertyChangeEventArgs e) {
// do something
}
Таким образом, всякий раз, когда класс OutsideBoard запускает событие PropertyChanged , все наблюдатели получат уведомление, вызвав свой MyClickHandling — метод.
Надеюсь, это вам поможет.
Комментарии:
1. Марк, спасибо. Использование 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.
}
Таким образом, событие щелчка на внешней панели будет обрабатываться как само по себе (без вашего вмешательства) Что вы делаете, так это просто добавляете дополнительный обработчик событий к этому элементу управления щелчком мыши 🙂
Комментарии:
1. Я думаю, чего я пытался избежать, так это того, что дочерние элементы знали о данных родителя. Событие происходит в дочернем элементе, но я пытаюсь выяснить, как подключить его, чтобы уведомить родительский элемент управления и уведомить другой пользовательский элемент управления, который является «родственным» из-за отсутствия лучшего термина.