I've been messing around with MVVM in WPF and have a quick question for folks. Right now I have:
- MainWindow which consists of a MenuBar and a UserControl
- UserControl (mentioned above) contains basically a Grid.
I expose access to Grid Properties as I need in the UserControl, but the User Control knows nothing nor interacts with the MainWindow.
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.
If I have that right, here is my question:
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:
private void RunQueryMenuItemAdvClick(object pSender, RoutedEventArgs pRoutedEventArgs) { ViewModel vViewModel = new ViewModel(this); vViewModel.RunQuery(); }
The View Model looks something like this:
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();
}
}
}
Am I way off base with my approach here?
EDIT New Solution: 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!
My ViewModel:
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 => this.RunQuery(),
param => 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();
}
}
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).