私は WPF で MVVM をいじっていて、人々に簡単な質問があります。今私は持っています:
- MenuBar と UserControl で構成される MainWindow
- UserControl (前述) には、基本的に Grid が含まれています。
UserControl で必要に応じて Grid プロパティへのアクセスを公開しますが、User Control は何も認識せず、MainWindow と対話しません。
MainWindow/UserControl を操作する ViewModel というクラスもあります。私の理解では、ViewModel は View (MainWindow/UserControl) とそれを操作する方法について知っていますが、View は通常 ViewModel について何も知りません。
私がその権利を持っている場合、ここに私の質問があります:
MainWindow MenuBar でボタンをクリックすると、アクションを実行したいと思います。現在、これらのアクションは MainWindow 内の EventHandler にバインドされており、EventHandler は ViewModel をインスタンス化し、次のように処理するためのメソッドを呼び出します。
private void RunQueryMenuItemAdvClick(object pSender, RoutedEventArgs pRoutedEventArgs) { ViewModel vViewModel = new ViewModel(this); vViewModel.RunQuery(); }
ビュー モデルは次のようになります。
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();
}
}
}
ここでの私のアプローチはベースから外れていますか?
新しいソリューションの編集: まず、応答してくれた皆さんに感謝します。新しいソリューションを提供したいと思います。これは 100% MVVM ではないかもしれませんが、私が持っていたものより少なくとも 80% 優れている必要があります!
私のビューモデル:
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();
}
}
MainWindow と UserControl の背後にあるすべてのコードを削除し、必要な要素を ViewModel と 1 Command の 2 つのプロパティにバインドするために XAML に置き換えました。私がリファクタリングで気づいたかもしれないし、気づいていないかもしれないことについて、追加のフィードバックをお気軽に提供してください。(モデルの使用法がないことは別として)。