验证MVVM WPF应用程序的问题

时间:2014-11-27 03:46:44

标签: c# wpf visual-studio validation mvvm

我正在尝试使用MVVM在WPF应用程序中实现验证,我相信我已经正确设置了验证但是当我测试它时它似乎没有在文本框上给我一个红色轮廓,因为很多例子我已在网上找到(例如https://www.youtube.com/watch?v=OOHDie8BdGI)。

为简单起见,我已将其缩小为一个标准,即Forename的文本框不会留空并删除其他属性。在我使用的指南和我自己的应用程序中的示例之间我唯一的区别是我的模型是在服务器上保存而View和ViewModel是客户端,这可能是导致问题的原因吗?

任何帮助都会非常感激,因为我已经在这几天挣扎了,谢谢!

RegistrationModel(服务器端)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Linq;
using System.Web;

namespace ScrumManagementWCFServices.Services.Registration
{
    [DataContract]
    public class RegistrationModel : IDataErrorInfo, INotifyPropertyChanged
    {
        private string forename;

        [DataMember]
        public string Forename
        {
            get 
            { 
                return forename;
            }
            set
            {
                forename = value;
                NotifyPropertyChanged("Forename");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region IDataErrorInfo Members

        string System.ComponentModel.IDataErrorInfo.Error
        {
            get { return null; }
        }

        string System.ComponentModel.IDataErrorInfo.this[string propertyName]
        {
            get
            {
                return GetValidationError(propertyName);
            }
        }

        #endregion

        #region Validation

        static readonly string[] ValidatedProperties = {/* "Email", */"Forename"/*, "Surname", "Password", "ConPassword"*/};

        public bool IsValid
        {
            get
            {
                foreach (string property in ValidatedProperties)
                    if (GetValidationError(property) != null)
                        return false;

                return true;
            }
        }

        string GetValidationError(String propertyName)
        {
            string error = null;

            switch (propertyName)
            {
                case "Forename":
                    error = validateForename();
                    break;
            }
            return error;
        }

        private string validateForename()
        {
            if (String.IsNullOrWhiteSpace(Forename))
            {
                return "Customer name cannot be empty.";
            }

            return null;
        }
    }
}

RegistrationPage(查看 - 客户端)

<Page x:Class="ScrumManagementApplication.Pages.LoginAndRegistrationPage.View.RegistrationPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:ScrumManagementApplication.Pages.LoginAndRegistrationPage.ViewModel"
      mc:Ignorable="d" 
      d:DesignHeight="300"
    Title="RegistrationView" Width="300">

    <Page.Resources>
        <local:RegistrationViewModel x:Key="DataContext"/>
    </Page.Resources>

    <Grid Background="#FFC0CAEC" DataContext="{StaticResource DataContext}" Margin="10">
        <TextBox Text="{Binding RegistrationModel.Forename, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Page>

RegistrationViewModel(客户端)

using ScrumManagementApplication.WCFRegistrationServiceReference;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.ComponentModel;
using ScrumManagementApplication.Pages.LoginAndRegistrationPage.View;
using System.Windows;

namespace ScrumManagementApplication.Pages.LoginAndRegistrationPage.ViewModel
{
    public class RegistrationViewModel : INotifyPropertyChanged
    {
        public RegistrationViewModel()
        {
            RegistrationModel = new RegistrationModel()
            {
                Forename = "Rick"
            };
        }

        public RegistrationModel RegistrationModel
        {
            get;
            set;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}

提前致谢!

2 个答案:

答案 0 :(得分:0)

您需要公开包装器属性并在视图模型上实现IDataErrorInfo或直接绑定到模型。验证不适用于{Binding RegistrationModel.Forename}

等绑定

答案 1 :(得分:0)

您可以使用System.ComponentModel.DataAnnotations Namespace简化一些事情。例如,如果您使用RequiredAttribute装饰Forename媒体资源,则当该字段为空时,您会在TextBox上看到所需的红色错误大纲:

[DataMember]
[Required(ErrorMessage="Customer name cannot be empty.")]
public string Forename
{
    get 
    { 
        return forename;
    }
    set
    {
        Validator.ValidateProperty(value, 
            new ValidationContext(this, null, null) { MemberName = "Forename" });
        forename = value;
        NotifyPropertyChanged("Forename");
    }
}

您可以在MSDN上的Using Data Annotations to Customize Data Classes页面上找到更多详细信息。你当然可以重构它以使用一个既验证又通知的方法 INotifyPropertyChanged界面。