Проверка данных (и привязка) в WPF с использованием MahApps и ReactiveUI - PullRequest
1 голос
/ 03 июля 2019

Я только начал использовать ReactiveUI и столкнулся с интересной проблемой.

Приложение, которое я пытаюсь создать, имеет своего рода бэкэнд, где я решил использовать Datagrid для отображения и редактирования собранных данных.из базы данных.

Все данные отображаются нормально, но я не могу понять, как мне привязать к проверке (и использовать MahApps, уже встроенные в ValidationErrorTemplate).

Итак, 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!");
            }

Дело в том, как я могу связать эти правила проверки с моим текущим кодом?

Если я не был достаточно ясен или у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь!

Заранее спасибо

...