Как сделать анимацию для кнопок внутри 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;
}

Вы должны иметь возможность обобщить это на несколько кнопок и использовать любую необходимую технику привязки данных. Хитрость в том, что вы должны переключаться между двумя визуальными состояниями, и вы можете делать это только в коде. И если у вас нет фиксированного количества элементов, вы можете также генерировать визуальные состояния в коде (но опять же, не связывая данные).

Другие вопросы по тегам