Как сделать анимацию для кнопок внутри DataTemplate через DataBinding.
У меня есть одно приложение в Windows Phone 8.1, где во время выполнения я генерирую несколько кнопок из ViewModel и помещаю их в Canvas, все кнопки размещаются на холсте в динамических местах. Теперь после некоторого условия я восстанавливаю другое количество кнопок и снова добавляю в пользовательский интерфейс Canvas. Каждый раз, когда я делаю это через ViewModel. Теперь мне нужны анимации в Canvas, когда игра переходит с метки 1 на метку 2.
GamePage.xaml содержит элемент управления canvas.
<Canvas Grid.Row="2" x:Name="gameCanvas" >
<ItemsControl ItemsSource="{Binding Path=ButtonItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Height="{Binding Height}"
Width="{Binding Width}"
Content="{Binding Content}">
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl>
</Canvas>
Можно ли запустить анимацию для Buttons
которые находятся внутри DataTemplate
? Если я хочу, чтобы стиль флип-кнопок, скажем, Label 1 Buttons
будет переворачиваться по горизонтали и исчезнет, и Label 2 buttons
появится перевернутый вертикально? Или любые непрозрачные анимации.
Я хочу сделать это через DataBinding
к некоторой собственности в ViewModel
, Я знаю, что в Windows Phone 8.1 <Style.Triggers>
не там. Так как же мне этого добиться? Любая помощь будет принята с благодарностью.
Спасибо
1 ответ
Примечание. Это решение может не работать со списком данных; Я не пробовал это. Но это работает, если вы можете назвать каждый элемент, добавленный в ваш пользовательский интерфейс (что должно быть сделано программно). Но если для вас важнее анимация, чем привязка данных к элементам, то это может сработать.
Предполагая, что у вас есть фиксированное количество элементов для перемещения, вы можете почти (но не совсем) сделать это с помощью Visual States. Вот пример, который показывает вам, как вы можете сделать это тривиально для одного Button
который перемещается случайным образом, когда вы нажимаете на него.
XAML
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.Resources>
<PowerEase Power="2" x:Key="PowerEase"/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VSG">
<VisualState x:Name="Default">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
Storyboard.TargetName="button" To="{Binding LeftOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="button" To="{Binding TopOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Other">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
Storyboard.TargetName="button" To="{Binding LeftOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="button" To="{Binding TopOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Canvas>
<Button x:Name="button" Content="Button" Height="100" Width="150" Click="button_Click"/>
</Canvas>
</Grid>
Код
public partial class VSM : PhoneApplicationPage, INotifyPropertyChanged
{
public VSM()
{
this.InitializeComponent();
DataContext = this;
random_ = new Random();
}
double left_;
double top_;
bool inOtherState_ = false;
Random random_;
public double LeftOffset { get { return left_; } }
public double TopOffset { get { return top_; } }
private void button_Click(object sender, RoutedEventArgs e)
{
left_ = random_.NextDouble() * (ActualWidth - 150);
top_ = random_.NextDouble() * (ActualHeight - 100);
RaisePropertyChanged();
if (inOtherState_)
VisualStateManager.GoToState(this, "Default", false);
else
VisualStateManager.GoToState(this, "Other", false);
inOtherState_ = !inOtherState_;
}
void RaisePropertyChanged()
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(""));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Вы должны иметь возможность обобщить это на несколько кнопок и использовать любую необходимую технику привязки данных. Хитрость в том, что вы должны переключаться между двумя визуальными состояниями, и вы можете делать это только в коде. И если у вас нет фиксированного количества элементов, вы можете также генерировать визуальные состояния в коде (но опять же, не связывая данные).