我对 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 查询非常复杂,我实现了一个异步运行这些查询的后台工作程序。
如何将数据导入到绑定(bind)到我的 View 的 ViewModel 中?还是我的设计方法整体上有问题?
我考虑过并尝试过的事情:
直接绑定(bind)到模型:可行,但有人告诉我这是一个
不好的做法,应用程序逻辑应该驻留在模型中。将 SQL 查询移动到 ViewModel 中:同样有效,但随后是我的模型 类似乎是多余的 - 它只不过是一种自定义数据类型。
同步运行查询并直接分配 Observable 我模型中的集合到我的 ViewModel 中的 Observable 集合。还 可以,但是我的 BackgroundWorker 遇到了问题, 因为 ViewModel 不知道查询何时真正完成。
最佳答案
- 将所有数据库逻辑移至服务(也称为存储库)类中。
- 可以直接绑定(bind)到模型属性,而不是为每个模型创建一打 ViewModel 代理类,只要您不需要围绕特定模型的任何特殊 View 相关逻辑。因此公开
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;
});
}
关于c# - 将模型中的异步更改通知 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35316999/