我一直在 WPF 中搞乱 MVVM,并有一个快速的问题要问人们。现在我有:
- MainWindow 由 MenuBar 和 UserControl 组成
- UserControl(上面提到的)基本上包含一个网格。
我根据需要在 UserControl 中公开对 Grid Properties 的访问,但 User Control 一无所知,也不与 MainWindow 交互。
我还有一个名为 ViewModel 的类,它为我操作 MainWindow/UserControl。我的理解是 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 后面删除了我的所有代码,并将其替换为 XAML,以便将我需要的元素绑定到 ViewModel 和 1 命令中的两个属性。随时提供关于我可能会或可能不会通过重构获得的额外反馈。(除了缺少模型用法)。