2011-07-17 14 views
0

私は単純なサウンドボードアプリケーションを作成しています。MVVMLightを使用して、リストボックスのdatatemplate内のトリガーアニメーションをMVVMLightを使用して

これは私のコードです。 私は事を単純に保つために何かを残してしまったのかどうか尋ねてください。

MainViewModelは、彼らは両方の任意のプロパティを変更するに通知され、

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

がsoundViewModelは、これらのプロパティが含まれ、このコレクションが含まれてい

public string FileName 
public string Name 
XAML/Viewはviewmodelの

にサウンドコレクションにバインドされたリストボックスが含まれています

<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(); 
    } 

これは素晴らしい作品にボタンにバインドされています。

ここでは、サウンド再生中に小さなアニメーションを再生します。 私は、アニメーションにサウンドクリップの長さを渡し、それを開始すると思っています。

メッセンジャークラスでは(上記、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エレメントです。 アニメーションは単に円弧要素のstartAngleであり、現在再生中のサウンドとサウンドの持続時間を示すためにのみ存在します。

何とか私はストーリーボードを取得する必要がありますが、targetElementはデータテンプレート内にあるので、正しいアニメーションの再生方法はどのようにわかりますか。それは私がストーリーボードへの参照を得ることさえできるのですか?

ありがとうございます! 何かがあるかどうか尋ねてください

+1

厳密に言えば、ViewModelはUI内で何もアニメートしてはいけません。ビューは、ViewModelの状態の変化を解釈し、いつ、何をアニメートするかを決定する必要があります。 – Will

+0

ええ、それは右のように聞こえるが、これは私がそれを動作させることができる唯一の方法です。 – Moulde

+1

Gotcha。しかし、あなたのビューでコードビハインドを割り引くトラップには入り込まないでください。このコードはビューの操作に関連しているだけで、簡単です... – Will

答えて

1

最初にデータテンプレートにアニメーションを定義してください。

次のようにCommandParameterを "FileName"にバインドする代わりに、アニメーションが定義されているデータテンプレートのオブジェクトにバインドします。通常、データテンプレートには、アニメーションがリソースとして定義されているルートレイアウトパネルが含まれます。それにx:Nameがあることを確認し、CommandParameterをバインドします。したがって、ルートレイアウトコンテナが「グリッド」と呼ばれていた場合、CommandParameterをこのようにバインドします。

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

ここで、リレーコマンドのハンドラで、ファイル名文字列ではなくFrameworkElementを渡すことを反映するようにパラメータを変更します。ストーリーボードを抽出するコードを変更し、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(); 
} 
+0

Uhh、私はviewmodelですべてのコードを保持することもできますし、ビューのコードビハインドに1行も書き込むことはできません。驚くばかり!ありがとうございました! – Moulde

関連する問題