Is access to ViewModel code always breaking the MVVM pattern?

One thing I'm really not sure about is to correctly pass mouse events into the ViewModel. There is a way to bind triggers using an extension of interactivity, for example, in: bind WPF events from View to ViewModel?

But this does not convey MouseEventArgs, as far as I know, and this solution seems to me not very elegant.

So what would be the right solution? One way is to register the event and process it in the code behind, for example:

    private void ListBox_PreviewMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
    {
        var listbox = sender as ListBox;

        if (listbox == null)
            return;

        var vm = listbox.DataContext as MainViewModel;

        if (vm == null)
            return;

        // access the source of the listbox in viewmodel
        double x = e.GetPosition(listbox).X;
        double y = e.GetPosition(listbox).Y;
        vm.Nodes.Add(new Node(x, y));
    }

Here I assume that the listbox ItemsSource is bound to the vm.Nodes property. So again, the question is: is this done correctly? Or is there a better one?

+4
2

, . , View, , ViewModel. GalaSoft.MvvmLight ( ), EventToCommand, PassEventArgsToCommand.

:

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <cmd:EventToCommand Command="{Binding FooCommand}"
                                PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

, . , - , -, . , ViewModel, View.

Some new notes

, MVVM, , View, View, - ViewModel , .

MVVM, , - " ", MVVM. :

  • Model of View

- , .

, :

MVVM WPF

+2

, , . , thnk , . MVVM Lite EventToCommand, /:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd ="http://www.galasoft.ch/mvvmlight"

, :

<ItemsControl ... etc ... >
    <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseDown">
                <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseDownCommand}" PassEventArgsToCommand="True" />
            </i:EventTrigger>
            <i:EventTrigger EventName="MouseUp">
                <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseUpCommand}" PassEventArgsToCommand="True" />
            </i:EventTrigger>
            <i:EventTrigger EventName="MouseMove">
                <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseMoveCommand}" PassEventArgsToCommand="True" />
            </i:EventTrigger>
        </i:Interaction.Triggers>

    </ItemsControl>

, ItemsControl, , . (, KeyDown), , . , , - :

public class MyViewModel : ViewModelBase
{
    public ICommand MouseDownCommand { get; set; }
    public ICommand MouseUpCommand { get; set; }
    public ICommand MouseMoveCommand { get; set; }
    public ICommand KeyDownCommand { get; set; }

    // I'm using a dependency injection framework which is why I'm
    // doing this here, otherwise you could do it in the constructor
    [InjectionMethod]
    public void Init()
    {
        this.MouseDownCommand = new RelayCommand<MouseButtonEventArgs>(args => OnMouseDown(args));
        this.MouseUpCommand = new RelayCommand<MouseButtonEventArgs>(args => OnMouseUp(args));
        this.MouseMoveCommand = new RelayCommand<MouseEventArgs>(args => OnMouseMove(args));
        this.KeyDownCommand = new RelayCommand<KeyEventArgs>(args => OnKeyDown(args));          
    }

    private void OnMouseDown(MouseButtonEventArgs args)
    {
        // handle mouse press here
    }

    // OnMouseUp, OnMouseMove and OnKeyDown handlers go here
}

, , , , , . , , . , "MouseCaptured" , . - , . , , - .

+4

All Articles