我刚刚开始使用ReactiveUI,遇到了一个有趣的问题。
我要构建的应用程序具有某种后端,在这里我决定使用Datagrid来显示和编辑从数据库中收集的数据。
所有数据均显示正常,但我无法理解如何绑定验证(并利用ValidationErrorTemplate中已内置的MahApps)。
因此,View xaml如下:
<reactiveUi:ReactiveUserControl
x:Class="diet_manager.View.FoodDatabaseView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:reactiveUi="http://reactiveui.net"
xmlns:viewModel="clr-namespace:diet_manager.ViewModel"
x:TypeArguments="viewModel:FoodDatabaseViewModel">
<DataGrid
x:Name="FoodDatabaseDataGrid"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"/>
</reactiveUi:ReactiveUserControl>
背后的代码:
using ReactiveUI;
namespace diet_manager.View
{
public partial class FoodDatabaseView
{
public FoodDatabaseView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
this.OneWayBind(ViewModel, vm => vm.Items, v => v.FoodDatabaseDataGrid.ItemsSource);
});
}
}
}
这是数据库视图模型:
using System.Collections.ObjectModel;
using diet_manager.Model;
using Splat;
namespace diet_manager.ViewModel
{
public class FoodDatabaseViewModel : ViewModelBase
{
public ObservableCollection<FoodViewModel> Items { get; }
public FoodDatabaseViewModel()
{
Items = new ObservableCollection<FoodViewModel>();
var manager = Locator.Current.GetService<FoodModelManager>();
foreach (var model in manager.GetAll())
{
Items.Add(new FoodViewModel(model, manager));
}
}
}
}
,最后是单个对象的视图模型(我想验证的对象):
using System;
using System.ComponentModel;
using System.Reactive.Linq;
using diet_manager.Model;
using ReactiveUI;
using ReactiveUI.Validation.Abstractions;
using ReactiveUI.Validation.Contexts;
using ReactiveUI.Validation.Extensions;
using ReactiveUI.Validation.Helpers;
namespace diet_manager.ViewModel
{
public class FoodViewModel : ReactiveObject, ISupportsValidation
{
private readonly FoodModel _foodModel;
private string _name;
private string _brand;
public ValidationContext ValidationContext { get; }
public ValidationHelper IdUniqueRule { get; }
public string Id => FoodModelDatabase.FoodIdGenerator(_foodModel.Name, _foodModel.Brand);
public string Name
{
get => _name;
set
{
this.RaiseAndSetIfChanged(ref _name, value);
this.RaisePropertyChanged(nameof(Id));
}
}
public string Brand
{
get => _brand;
set
{
this.RaiseAndSetIfChanged(ref _brand, value);
this.RaisePropertyChanged(nameof(Id));
}
}
public FoodViewModel(FoodModel foodModel, FoodModelManager manager)
{
ValidationContext = new ValidationContext();
_foodModel = foodModel;
this.ValidationRule(
vm => vm.Name,
name => !string.IsNullOrWhiteSpace(name),
$"{nameof(Name)} cannot be null or whitespace!");
var isIdUnique = this.WhenAnyValue(vm => vm.Name, vm => vm.Brand, (name, brand) => new FoodModelBundle { Name = name, Brand = brand }).Select(x => !manager.TryGet(x, out _));
IdUniqueRule = this.ValidationRule(
_ => isIdUnique,
(vm, state) => $"The proposed Id {FoodModelDatabase.FoodIdGenerator(_name, _brand)} is already in use.\nTry changing Name and Brand to avoid this problem!");
}
重点是: 如何用当前代码绑定到此验证规则?
如果我不够清楚,或者您有任何问题要问,请随时这样做!
提前谢谢