Note that there are some explanatory texts on larger screens.

plurals
  1. POView and View-Model in WPF
    text
    copied!<p>I've been messing around with MVVM in WPF and have a quick question for folks. Right now I have:</p> <ul> <li>MainWindow which consists of a MenuBar and a UserControl </li> <li>UserControl (mentioned above) contains basically a Grid.</li> </ul> <p>I expose access to Grid Properties as I need in the UserControl, but the User Control knows nothing nor interacts with the MainWindow.</p> <p>I also have a class I call ViewModel which does manipulation of the MainWindow/UserControl for me. My understanding is that the ViewModel knows about the View (MainWindow/UserControl) and how to manipulate it while the View generally knows nothing about the ViewModel.</p> <p>If I have that right, here is my question:</p> <ol> <li><p>When I do button clicks on the MainWindow MenuBar I want to perform actions. Right now those actions are bound to say a EventHandler in the MainWindow and the EventHandler instantiates the ViewModel and calls the method for handling like such:</p> <pre><code>private void RunQueryMenuItemAdvClick(object pSender, RoutedEventArgs pRoutedEventArgs) { ViewModel vViewModel = new ViewModel(this); vViewModel.RunQuery(); } </code></pre></li> </ol> <p>The View Model looks something like this:</p> <pre><code> public class ViewModel { private DataProvider fDataProvider; private MainWindow fMainWindow; private BackgroundWorker fQueryWorker = new BackgroundWorker(); public ViewModel(MainWindow pMainWindow) { fDataProvider = new DataProvider(); fMainWindow = pMainWindow; //Query Worker fQueryWorker.DoWork += QueryWorkerDoWork; fQueryWorker.RunWorkerCompleted += QueryWorkerCompleted; } private void QueryWorkerCompleted(object pSender, RunWorkerCompletedEventArgs pRunWorkerCompletedEventArgs) { fMainWindow.UserControl_Data.busyIndicator1.IsBusy = false; fMainWindow.UserControl_Data.DataToPresent = pRunWorkerCompletedEventArgs.Result; } private void QueryWorkerDoWork(object pSender, DoWorkEventArgs pDoWorkEventArgs) { pDoWorkEventArgs.Result = this.fDataProvider.GetParticipantsData(); } public void RunQuery() { if (!fQueryWorker.IsBusy) { fMainWindow.UserControl_Data.busyIndicator1.IsBusy = true; fQueryWorker.RunWorkerAsync(); } } } </code></pre> <p>Am I way off base with my approach here?</p> <p><em><strong>EDIT New Solution:</em></strong> First, thanks to everyone for their response. I'd like to provide my new solution. This may not be 100% MVVM, but it has to be at least 80% better than what I had!</p> <p>My ViewModel:</p> <pre><code> public class ViewModel : ObservableObject { private DataProvider fDataProvider; private BackgroundWorker fQueryWorker = new BackgroundWorker(); public ViewModel() { fDataProvider = new DataProvider(); //Query Worker fQueryWorker.DoWork += QueryWorkerDoWork; fQueryWorker.RunWorkerCompleted += QueryWorkerCompleted; } //This is my Command for the MainWindow.MenuItem to bind to to run a query RelayCommand fRunQueryCommand; public ICommand RunQueryCommand { get { if (this.fRunQueryCommand == null) { this.fRunQueryCommand = new RelayCommand(param =&gt; this.RunQuery(), param =&gt; true); } return this.fRunQueryCommand; } } //This is my Property for the UserControl.progressBar to bind to private bool fIsBusy; public bool IsBusy { get { return this.fIsBusy; } set { if (value != this.fIsBusy) { this.fIsBusy = value; OnPropertyChanged("IsBusy"); } } } //This is my Property for the UserControl.gridControl.ItemSource to bind to private object fSource; public object Source { get { return this.fSource; } set { if (value != this.fSource) { this.fSource = value; OnPropertyChanged("Source"); } } } private void QueryWorkerCompleted(object pSender, RunWorkerCompletedEventArgs pRunWorkerCompletedEventArgs) { this.IsBusy = false; Source = pRunWorkerCompletedEventArgs.Result; } private void QueryWorkerDoWork(object pSender, DoWorkEventArgs pDoWorkEventArgs) { pDoWorkEventArgs.Result = this.fDataProvider.GetParticipantsData(); } public void RunQuery() { if (!fQueryWorker.IsBusy) { this.IsBusy = true; fQueryWorker.RunWorkerAsync(); } } </code></pre> <p>I've removed all of my code from behind the MainWindow and the UserControl and replaced it with XAML for Binding the elements that I needed to the two properties in ViewModel and the 1 Command. Feel free to provide additional feedback on what I may or may not have picked up on with the re-factoring. (Aside from the lack of a Model usage).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload