IDataErrorInfo - 即使收到错误消息也没有看到任何错误消息

发布于 2024-11-03 23:08:05 字数 4435 浏览 0 评论 0原文

我有 ItemType,它在 IDataErrorInfo 接口的帮助下实现了验证所需的一切:

#region IDataErrorInfo implementation
        //WPF doesn't need this one
        public string Error
        { get { return null; } }

        public string this[string propertyName]
        {
            get { return GetValidationError(propertyName); }
        }
        #endregion

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

                return true;
            }
        }

        static readonly string[] ValidatedProperties =
        {
            "Name"
        };

        private string GetValidationError(string propertyName)
        {
            if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
                return null;

            string error = null;

            switch (propertyName)
            {
                case "Name":
                    error = ValidateName();
                    break;
                default:
                    Debug.Fail("Unexpected property being validated on Customer: " + propertyName);
                    break;
            }

            return error;
        }

        string ValidateName()
        {
            if (!IsStringMissing(Name))
            {
                return "Name can not be empty!";
            }

            return null;
        }

        static bool IsStringMissing(string value)
        {
            return string.IsNullOrEmpty(value) ||
                   value.Trim() == String.Empty;
        }
        #endregion

ItemType 用 ItemViewModel 包装。在 ItemViewModel 上,当用户单击“保存”按钮时,我有一个命令:

public ICommand SaveItemType
        {
            get
            {
                if (saveItemType == null)
                {
                    saveItemType = new RelayCommand(() => Save());
                }

                return saveItemType;
            }
        }

然后,在 DetailsView 中,我有以下 xaml 代码:

<TextBlock Text="Name:" />
<TextBox Grid.Column="1" Name="NameTextBox" Text="{Binding Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
                         Validation.ErrorTemplate="{x:Null}" />

<ContentPresenter Grid.Row="13" Grid.Column="2"
                  Content="{Binding ElementName=NameTextBox, Path=(Validation.Errors).CurrentItem}" />

正在进行以下架构(尚不清楚,但表单实际上是一个独立的 xaml 文件(用户控件),其中表单中网格的数据上下文设置为 ObservableCollection):

<Grid DataContext="{Binding Items}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

在此处输入图像描述

问题我遇到的问题是错误消息没有显示。当我断点并检查它是否正确验证以及是否有任何错误消息时,我确实有它们。但不知何故,错误消息没有到达 xaml 中。

拼图中缺失的一块是什么?

编辑 - 缺失的部分

对,所以,它是什么:

我在我的模型上实现了 IDataErrorInfo,但没有在包装模型的 ViewModel 上实现。我所要做的就是在 ViewModel 上实现 IDataErrorInfo 接口,并从模型中获取它。

IDataErrorInfo 的 ViewModel 实现:

{ get { return (ItemType as IDataErrorInfo).Error; } }

public string this[string propertyName]
{
  get
  {
    return (ItemType as IDataErrorInfo)[propertyName];
  }
}

I have ItemType that implements everything one would need for Validation with the help of IDataErrorInfo interface:

#region IDataErrorInfo implementation
        //WPF doesn't need this one
        public string Error
        { get { return null; } }

        public string this[string propertyName]
        {
            get { return GetValidationError(propertyName); }
        }
        #endregion

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

                return true;
            }
        }

        static readonly string[] ValidatedProperties =
        {
            "Name"
        };

        private string GetValidationError(string propertyName)
        {
            if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
                return null;

            string error = null;

            switch (propertyName)
            {
                case "Name":
                    error = ValidateName();
                    break;
                default:
                    Debug.Fail("Unexpected property being validated on Customer: " + propertyName);
                    break;
            }

            return error;
        }

        string ValidateName()
        {
            if (!IsStringMissing(Name))
            {
                return "Name can not be empty!";
            }

            return null;
        }

        static bool IsStringMissing(string value)
        {
            return string.IsNullOrEmpty(value) ||
                   value.Trim() == String.Empty;
        }
        #endregion

ItemType is wrapped with ItemViewModel. On the ItemViewModel I have a command for when a user clicks the Save Button:

public ICommand SaveItemType
        {
            get
            {
                if (saveItemType == null)
                {
                    saveItemType = new RelayCommand(() => Save());
                }

                return saveItemType;
            }
        }

Then, in the DetailsView, I have the following xaml code:

<TextBlock Text="Name:" />
<TextBox Grid.Column="1" Name="NameTextBox" Text="{Binding Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
                         Validation.ErrorTemplate="{x:Null}" />

<ContentPresenter Grid.Row="13" Grid.Column="2"
                  Content="{Binding ElementName=NameTextBox, Path=(Validation.Errors).CurrentItem}" />

the following architecture going on (it is not clear, but the form is actually an independent xaml file (User Control), where the datacontext of the grid in the form is set to the ObservableCollection):

<Grid DataContext="{Binding Items}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

enter image description here

The problem that I am having is that error messages are not showing up. When I breakpoint and check if it validates correctly and if I have any error messages, then I do have them. But somehow the error message does not arrive in the xaml.

What is the missing piece of the puzzle?

EDIT - THE MISSING PIECE

Right, so, what it was was the following:

I implemented IDataErrorInfo on my model, but not on the ViewModel that wraps the model. What I had to do was as well was implement the IDataErrorInfo interface on the ViewModel, and get it from the model.

ViewModel Implementation of IDataErrorInfo:

{ get { return (ItemType as IDataErrorInfo).Error; } }

public string this[string propertyName]
{
  get
  {
    return (ItemType as IDataErrorInfo)[propertyName];
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白云不回头 2024-11-10 23:08:05

我使用以下样式来查看我的验证是否发生。

<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
    <Style.Triggers>>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors).CurrentItem.ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            <Setter Property="Background" Value="{StaticResource BrushErrorLight}" />
        </Trigger>
    </Style.Triggers>
</Style>

您应该在工具提示中看到验证消息

编辑:

尝试将 NotifyOnValidationError=true 添加到您的绑定中

<TextBox Grid.Column="1" Name="NameTextBox" 
         Text="{Binding Name, ValidatesOnDataErrors=True, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}" />

i use the follwoing style to see wether my validation occurs or not.

<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
    <Style.Triggers>>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors).CurrentItem.ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            <Setter Property="Background" Value="{StaticResource BrushErrorLight}" />
        </Trigger>
    </Style.Triggers>
</Style>

you should see the validationmessage in your tooltip

EDIT:

try to add NotifyOnValidationError=true to your binding

<TextBox Grid.Column="1" Name="NameTextBox" 
         Text="{Binding Name, ValidatesOnDataErrors=True, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}" />
我三岁 2024-11-10 23:08:05

我遇到了类似的问题,并通过将经过验证的元素放入 AdornerDecorator。可能值得尝试。

I had a similar problem, and fixed it by putting the validated element inside an AdornerDecorator. Might be worth trying.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文