2

Basically, I'm not sure how to use MVVM, and/or use commands correctly in my current situation. So, I have a View, containing a list box, and a panel of animation objects, that I created. These animation objects can be animated through a simple public method, Animate(). The goal here, is to associate this Animate() method with buttons inside the list box, like so:

As we can see in the diagram below, both the ListBox items and the visual elements inside of the animation area are associated with the same collection of models from the ViewModel, with the items in each being templated. For example, the ListBox items are simply defined to have some text related to a data item, and the AnimationObjects take on an appearance according to the data. These models, I feel, should not understand that an animation is occurring - they're simple data, and the animation does not change them. Finally, I show in the below diagram, that I have created two FrameworkElement child types, one for holding animation objects, and another that defines these animation objects. How can I connect this animation action to the buttons within the list box? It doesn't make sense to me that the models/viewmodels know about the animation, because it doesn't change the state of anything in my application - it's just for visual purposes. I've thought about using a RoutedCommand defined in AnimationObject, and having the buttons bind their command property accordingly, but I worry that will simply make every element animate at the same time.

It is also important for my sake, that I conform to MVVM, as these data will be used in many other situations, perhaps even a different version of this view.

Any advice would be appreciated.

  • 1
    possible duplicate of [How can I Have a WPF EventTrigger on a View trigger when the underlying Viewmodel dictates it should?](http://stackoverflow.com/questions/1424202/how-can-i-have-a-wpf-eventtrigger-on-a-view-trigger-when-the-underlying-viewmode) – Tetsujin no Oni Feb 10 '15 at 22:10
  • @TetsujinnoOni, thanks for sharing that link; however, I'm not sure it really helps me. With their problem, they made use of a storyboard to change the visuals. With mine, I really need to use that Animate() method. Do you know of a way to bridge the two problems? – Michael Alexander Feb 10 '15 at 22:15
  • 1
    Do you need to do anything else inside the command besides trigger the animation? Really the view model shouldn't know anything about the animation or even that it is animating as that is view specific information, so really it can just be triggered in the view and handled completely by the view. – ndonohoe Feb 12 '15 at 10:54
  • @bonyjoe, thanks, though I kind of already said as much. Do you suggest using purely a trigger, then? I'm not sure how to accomplish such a thing, as the animationobjects aren't really above or below the listbox items in the visual tree. Their only relationship is through their common data binding. – Michael Alexander Feb 12 '15 at 21:38
  • I would probably say use a click handler, bind some identifiable data such as an ID to the button tag and the same to the animation object tag. Then in the click handler find the correct animation object based on the senders tag and call the animate method. It encapsulates the view logic in the view and doesn't tie it directly to the viewmodel. – ndonohoe Feb 13 '15 at 10:59

1 Answers1

1

What you can do is call a command in your ViewModel , i.e. the DataContext of your ListBox.

CS :

public class ViewModel
{
    public ICommand AnimateObjectCommand { get; }
} 

XAML :

<DataTemplate x:Key="AnimationObjectItemTemplate">
    <Button Command="{Binding Path=DataContext.AnimateObjectCommand, RelativeSource={RelativeSource AncestorType=ListBox}}" 
            CommandParameter="{Binding}" />
</DataTemplate>

<ListBox ItemsSource="{Binding AnimationObjects}" ItemTemplate="{StaticResource AnimationObjectItemTemplate}"/>

your Command implementation should be one that accepts an argument which would be passed by the CommandParameter .

    private ICommand _animateObjectCommand;
    public ICommand AnimateObjectCommand
    {
        get
        {
            if (_animateObjectCommand == null)
            {
                _animateObjectCommand = new RelayCommand<AnimationObject>( ao => { ao.Animate(); });
            }
            return _animateObjectCommand;
        }
    }

The CommandParameter = {Binding} meaning this.DataContext where this is an Item in your ListBox and it's DataContext is an AnimationObject.

eran otzap
  • 12,293
  • 20
  • 84
  • 139