使用MVVMLight从viewmodel触发listbox datatemplate内的动画

时间:2011-07-17 23:34:26

标签: silverlight windows-phone-7 mvvm mvvm-light

要学习WP7,我正在制作一个简单的音板应用程序。

这是我的代码。 请问我是否在试图让事情变得简单时不小心留下了一些东西。

MainViewModel包含此集合

public ObservableCollection<SoundViewModel> Sounds { get; private set; }

soundViewModel包含这些属性,它们都通知任何属性更改

public string FileName
public string Name

Xaml / View包含绑定到viewmodel

上的Sounds集合的列表框
<ListBox x:Name="FirstListBox" Margin="0,0,-12,0" ItemsSource="{Binding Sounds}">
   <ListBox.ItemTemplate>
      <DataTemplate>
          <Button Content="Play" CommandParameter="{Binding FileName}" Command="{Binding DataContext.PlaySound, ElementName=FirstListBox}" />
<es:Arc x:Name="arc" ..bla bla attributes. />
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

当我点击按钮时,参数/文件名用于定位文件并调用以下方法。

此方法包含在RelayCommand中,并绑定到datatemplate

中的按钮
    private void PlaySound( string filename )
    {
        Stream stream = TitleContainer.OpenStream(filename + ".wav");
        SoundEffect effect = SoundEffect.FromStream(stream);
        PlayAnimation message = new PlayAnimation(effect.Duration);
        Messenger.Default.Send<PlayAnimation>(message);
        FrameworkDispatcher.Update();
        effect.Play();
    }

这很有效。

现在我希望在播放声音时播放小动画。 我想我只会将声音剪辑的长度传递给动画,然后启动它。

messenger类发送一条消息(在上面的PlaySound方法中),这段代码将它连接到一个方法

    ------ View / Xaml Constructor ------
    Messenger.Default.Register<PlayAnimation>(this, ( action ) => PlayAnimation(action));

    ------ method PlayAnimation below ------
    private void PlayAnimation(PlayAnimation parameter)
    {
        //Magic code starting the animation in the datatemplate of the listbox..
    }

但我不确定如何启动动画。

故事板是列表框的资源,targetElement是Arc元素。 所以动画就是arc元素的startAngle,就是说明我当前正在播放的声音,以及声音持续时间有多长。

不知怎的,我需要掌握故事板,但由于targetElement在数据模板中,我怎么知道如何播放正确的动画。那就是如果我甚至能够参考故事板?

提前致谢! 请询问是否有任何内容

1 个答案:

答案 0 :(得分:1)

首先在数据模板中定义动画。

接下来,不将CommandParameter绑定到“FileName”,而是将其绑定到数据模板中定义动画的对象。通常,您的数据模板将包含根布局面板,其中动画被定义为资源。确保它有一个x:Name并将CommandParameter绑定到该名称。因此,如果您的根布局容器被称为“grid”,请将CommandParameter绑定到它。

CommandParameter="{Binding ElementName=grid, Mode=OneWay}" 

现在,在relay命令的处理程序中,更改参数以反映您现在传递的是FrameworkElement而不是文件名字符串。还要更改代码以提取Storyboard并使用DataContext返回到viewmodel以获取声音的文件名。

private void PlaySound( FrameworkElement obj )
{
    var animation = obj.Resources["MyAnimation"] as Storyboard;
    animation.Begin();

    var selected = obj.DataContext as SoundViewModel;
    var filename = selected.FileName;

    Stream stream = TitleContainer.OpenStream(filename + ".wav");
    SoundEffect effect = SoundEffect.FromStream(stream);
    PlayAnimation message = new PlayAnimation(effect.Duration);
    Messenger.Default.Send<PlayAnimation>(message);
    FrameworkDispatcher.Update();
    effect.Play();
}