using EventToCommand & PassEventArgsToCommand :: how to get sender, or better metaphor?

StackOverflow https://stackoverflow.com/questions/4627683

  •  30-09-2019
  •  | 
  •  

Question

The point of what I'm doing is that there are a lot of things that need to happen in the viewmodel, but when the view has been loaded, not on constructor. I could wire up event handlers and send messages, but that just seems kinda sloppy to me. I'm implementing a base view and base viewmodel where this logic is contained so all my views get it by default, hopefully.

Perhaps I can't even get what I'm wanting: the sender. I just figured this is what RoutedEventArgs.OriginalSource was supposed to be?

[Edit] In the meantime, I've hooked up an EventHandler in the xaml.cs, and sure enough, OriginalSource is null there as well. So I guess really I need to know if it's possible to get a reference to the view/sender in the Command as well? [/Edit]

My implementation requires that a helper class to my viewmodels which is responsible for creating 'windows' knows of the 'host' control that all the windows get added to. i'm open to suggestions for accomplishing this outside the scope of using eventtocommand. :)

(the code for Unloaded is the same)

    #region ViewLoadedCommand
    private RelayCommand<RoutedEventArgs> _viewLoadedCommand = null;
    /// <summary>
    /// Command to handle the control's Loaded event. 
    /// </summary>
    public RelayCommand<RoutedEventArgs> ViewLoadedCommand
    {
        get
        {
            // lazy-instantiate the RelayCommand on first usage
            if (_viewLoadedCommand == null)
            {
                _viewLoadedCommand = new RelayCommand<RoutedEventArgs>(
                    e => this.OnViewLoadedCommand(e));
            }
            return _viewLoadedCommand;
        }
    }
    #endregion ViewLoadedCommand


    #region View EventHandlers
    protected virtual void OnViewLoadedCommand(RoutedEventArgs e)
    {
        EventHandler handler = ViewLoaded;
        if (handler != null)
        {
            handler(this, e);
        }
    }
    #endregion
Was it helpful?

Solution

Joe,

My stance on MVVM is:
View : knows about ViewModel
ViewModel : knows about Model (has NO knowledge of View)
Model : holds data. (has NO knowledge of ViewModel, View)

If I was in your situation, I would have the base ViewModel implement a custom interface IViewModel. (In fact, I have an IViewModel interface which is implemented by my public abstract class ViewModelBase and all my ViewModels inherit ViewModelBase.)

public interface IViewModel
{  
   void Load();
   void UnLoad();
   // other Properties, Methods, etc.
}
public abstract class ViewModelBase : IViewModel
{
   public virtual/*or abstract*/ void Load()
   {
      // code
   }
}

then in your View:

this.Loaded += (o, e) => { if(ViewModel != null) { ViewModel.Load(); } }  

Finally, to distinguish among specific Views and/or ViewModels, I use a public string Token (Guid-generated).

OTHER TIPS

I try to solve these problems with straight xaml and commanding when possible. I've used the EventToCommand on the View (UserControl) itself like this:

<i:Interaction.Triggers>
  <i:EventTrigger EventName="Loaded">
    <mvvmlight:EventToCommand Command="{Binding LoadCommand}" />
  </i:EventTrigger>
</i:Interaction.Triggers>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top