使用MahApps和ReactiveUI在WPF中进行数据验证(和绑定)

时间:2019-07-03 13:29:27

标签: c# wpf reactiveui mahapps.metro

我刚刚开始使用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!");
            }

重点是:     如何用当前代码绑定到此验证规则?

如果我不够清楚,或者您有任何问题要问,请随时这样做!

提前谢谢

0 个答案:

没有答案