我对MVVM比较陌生,我想知道构建应用程序的最佳方法。以下是我的模型示例:
public class ModelSource : ModelBase
{
#region Fields
private int _isLoading;
private BackgroundWorker worker = new BackgroundWorker();
private ObservableCollection<PCDatabase> _databases;
#endregion //Fields
#region Properties
public ObservableCollection<PCDatabase>Databases
{
get
{
if (_databases == null)
{
_databases = new ObservableCollection<PCDatabase>();
}
return _databases;
}
set
{
_databases = value;
this.OnPropertyChanged("Databases");
}
}
public int IsLoading
{
get
{
return _isLoading;
}
set
{
_isLoading = value;
OnPropertyChanged("IsLoading");
}
}
#endregion
#region Methods
/// <summary>
/// Gets all Databases from the Server
/// </summary>
public void getDatabasesAsync(ConfigDatabaseConnection _currentConfig)
{
//execute SQL Query...
}
(ModelBase实现了INotifyPropertyChanged)。
这是我对应的ViewModel:
namespace DbRestore.ViewModel
{
public class ViewModelSource : ViewModelBase
{
private ObservableCollection<PCDatabase> _databases;
private ModelSource _modelSource;
private ICommand _populateDatabaseCommand;
public ConfigDatabaseConnection _currentConfig;
public ViewModelSource()
{
this.ModelSource = new ModelSource();
}
#region Commands
/// <summary>
/// Command that opens a Database Connection Dialog
/// </summary>
public ICommand OpenDataBaseConnectionCommand
{
get
{
if (_populateDatabaseCommand == null)
{
_populateDatabaseCommand = new RelayCommand(
param => this.PopulateDatabases()
);
}
return _populateDatabaseCommand;
}
}
public ObservableCollection<PCDatabase> Databases
{
get
{
return _databases;
}
set
{
_databases = value;
OnPropertyChanged("Databases");
}
}
#endregion //Commands
public void PopulateDatabases()
{
ModelSource.getDatabasesAsync(_currentConfig);
}
调用ModelSource.getDatabasesAsync(_currentConfig)在我的模型中获取我的SQL数据。由于我的一些SQL查询非常复杂,我实现了一个异步运行这些查询的后台工作程序。
如何将数据存入我的ViewModel,该ViewModel绑定到我的View?或者我的设计方法总体上是错误的?
我考虑过并尝试过的事情:
直接绑定到模型:工作,但我被告知这是一个
不好的做法,应用程序逻辑应该驻留在模型中。
将SQL查询移动到ViewModel中:也可以,但后来我的模型 class似乎是多余的 - 它只是一个自定义数据类型。
同步运行查询并直接分配Observable 我的模型中的集合在我的ViewModel中的Observable Collection中。也 工作,但后来我遇到了BackgroundWorker的问题, 因为ViewModel不知道查询实际完成的时间。
答案 0 :(得分:2)
PCDatabase
的集合是可以的。由于您使用的是BackgroundWorker
,我假设您使用的是.NET Framework 3.5并且没有TPL。
public interface IPCDatabaseRepository
{
void GetPCDatabasesAsync(Action<IList<PCDatabase>> resultHandler);
}
public class PCDatabaseRepository : IPCDatabaseRepository
{
public void GetPCDatabasesAsync(Action<IList<PCDatabase>> resultHandler)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, args) =>
{
args.Result = // Execute SQL query...
};
worker.RunWorkerCompleted += (sender, args) =>
{
resultHandler(args.Result as IList<PCDatabase>);
worker.Dispose();
};
worker.RunWorkerAsync();
}
}
public class ViewModelSource : ViewModelBase
{
private readonly IPCDatabaseRepository _databaseRepository;
private ObservableCollection<PCDatabase> _databases;
private bool _isBusy;
public ViewModelSource(IPCDatabaseRepository databaseRepository /*Dependency injection goes here*/)
{
_databaseRepository = databaseRepository;
LoadDatabasesCommand = new RelayCommand(LoadDatabases, () => !IsBusy);
}
public ICommand LoadDatabasesCommand { get; private set; }
public ObservableCollection<PCDatabase> Databases
{
get { return _databases; }
set { _databases = value; OnPropertyChanged("Databases"); }
}
public bool IsBusy
{
get { return _isBusy; }
set { _isBusy = value; OnPropertyChanged("IsBusy"); CommandManager.InvalidateRequerySuggested(); }
}
public void LoadDatabases()
{
IsBusy = true;
_databaseRepository.GetPCDatabasesAsync(results =>
{
Databases = new ObservableCollection(results);
IsBusy = false;
});
}
答案 1 :(得分:1)
异步编程:异步MVVM应用程序的模式:数据绑定 https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
异步编程:异步MVVM应用程序的模式:命令 https://msdn.microsoft.com/en-us/magazine/dn630647.aspx
这些应该涵盖一个好的策略,尤其是在使用async / await时。