我已经阅读了许多有关如何在WPF-MVVM中验证数据的文章,但是比起我开始更加困惑。

我想做的就是简单地向数据库添加新行。验证检查设备名称(要插入的对象)是否超过2个字符长我想检查其唯一性,因此这会引起问题。

据我所知Model应该注意自己的验证:例如字符长度,电子邮件地址有效性(如果具有电子邮件属性)等。但是,如何访问数据层以检查唯一性呢?根据我的理解,模型不应该知道有关该层的任何信息。现在,此验证规则已成为“业务”规则。

这是我的 RegisterViewModel :

class RegisterViewModel : ViewModelBase, IDataErrorInfo
{

    private string _DeviceName = "";
    public string DeviceName
    {
        get { return _DeviceName; }
        set
        {
            _DeviceName = value;
            OnPropertyChanged("DeviceName");
        }
    }

    public string Error
    {
        get
        {
            throw new NotImplementedException();
        }
    }
    // We'd also check for uniqueness here?
    public string this[string columnName]
    {
        get
        {
            string result = null;
            if (columnName == "DeviceName" && String.IsNullOrEmpty(DeviceName))
            {
                return "Device name is required";
            }
            return result;
        }
    }

    public RegisterViewModel()
    {
        DeviceName = System.Environment.MachineName;
    }


    public ICommand Register { get; set; }

}

当然,有些人会认为IDataErrorInfo应该在Model类中实现,我会有些同意,但是同样,整个唯一性问题仍然存在。

这是我的 device 模型:
public partial class device
{
    public int did { get; set; }
    public int uid { get; set; }
    public string Name { get; set; }
}

最后, View
<Window x:Class="IPdevices.Register"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IPdevices"
        mc:Ignorable="d"
        Title="Register" Height="202.884" Width="417.007" Icon="logo31_nowriting.ico" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
    <Grid>
        <GroupBox x:Name="groupBox" Header="Device" VerticalAlignment="Top" RenderTransformOrigin="0.877,2.187" Margin="10,10,10,0" Height="96">
            <Grid Margin="0,0,3,3">
                <Grid.RowDefinitions>
                    <RowDefinition Height="47*"/>
                    <RowDefinition Height="49*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="146*"/>
                    <ColumnDefinition Width="197*"/>
                </Grid.ColumnDefinitions>
                <TextBox x:Name="textBox" Height="24" TextWrapping="Wrap"  VerticalAlignment="Top" Grid.Column="1" Margin="0,6,0,0" Text="{Binding Path=DeviceName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, NotifyOnValidationError=true}">
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Style.Triggers>
                                <Trigger Property="Validation.HasError" Value="True">
                                    <Setter Property="Background" Value="Red"/>
                                    <Setter Property="ToolTip"
                                        Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                                        Path=(Validation.Errors)[0].ErrorContent}"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
                <Label x:Name="label" Content="Device Name:" RenderTransformOrigin="1.372,1.475" Margin="10,2,10,0" Height="28" VerticalAlignment="Top"/>
                <TextBox x:Name="textBox1" Height="23" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Margin="0,7,0,0" Grid.Row="1" Grid.Column="1"/>
                <Label x:Name="label1" Content="Location:" Margin="10,3,10,0" Grid.Row="1" Height="27" VerticalAlignment="Top"/>
            </Grid>
        </GroupBox>
        <Button x:Name="button" Content="Register" Height="25" VerticalAlignment="Top" Margin="10,129,10,0" IsDefault="True" ToolTip="Register" Command="{Binding Register}"/>
    </Grid>
</Window>

此时,验证成功,并且弹出红色轮廓。虽然我不确定如何处理设备名称的uniqueness属性。最重要的是,如何使“注册”按钮仅在一切都通过后才变为 Activity 状态?

任何输入将不胜感激。

最佳答案

公平的难题。当涉及数据验证时,您可以采用不同的方法,并且它们通常都可以正常工作。

因此,我将发表我的个人看法。阅读我写的有关MVVM的post可能有助于您理解我的立场。因此,让我们尝试回答您的每个问题:



是的,只要有可能,但是如您所见,您可能需要做更多的工作来进行一些验证



这是设计决定,但我通常会同意。



我真的不明白为什么?要特别小心“商务”一词。这种独特性是您的业务专家的真正要求吗?还是仅仅是技术规则,因为否则您就无法将其存储在关系数据库中?

无论如何,在我看来,当您需要某种东西来验证多个模型,或者需要某种东西来验证一个模型但使用外部数据(例如在您的示例中)时,它就被称为服务,它应该围绕用例构建(在我的案例中) post我以购买服务为例)



我认为IDataErrorInfo的设计是对世界的一种非常简单的看法。它可以在很少的CRUD应用程序中工作,但是在管理实际的业务应用程序时并不十分方便。我认为您不应该使用它。只需在 View 模型中添加属性,即可自行管理红色弹出窗口和内容。确实没有那么难,设置一个红色边框,在验证后更改您的属性,然后完成。



您的用例是什么?围绕此用例创建服务,并验证设备在该服务中的唯一性。



忘记IDataErrorInfo,自己实现即可。每当用户界面中的属性更新时,请再次调用您的验证服务。如果一切顺利,请激活您的按钮,否则请向用户指定错误的原因。

是否有意义?

关于c# - 错误处理WPF-MVVM,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39084276/

10-14 12:00