WPF验证(IDataErrorInfo)和动态加载用户控件时出现问题

WPF验证(IDataErrorInfo)和动态加载用户控件时出现问题,wpf,validation,user-controls,Wpf,Validation,User Controls,我有一个用户控件,我使用(IDataErrorInfo)进行验证问题是,当我动态加载用户控件时,验证不会第一次出现,但当我在设计时加载它时,它工作了。问题是什么? 这是用户控件 <UserControl x:Class="WeaponLibrary.WeaponUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://sc

我有一个用户控件,我使用(IDataErrorInfo)进行验证问题是,当我动态加载用户控件时,验证不会第一次出现,但当我在设计时加载它时,它工作了。问题是什么? 这是用户控件

 <UserControl x:Class="WeaponLibrary.WeaponUserControl"
         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:WeaponLibrary"
         xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
         xmlns:ad="clr-namespace:DataAccessClassLibrary.ValidationRules;assembly=DataAccessClassLibrary"
         mc:Ignorable="d"
         d:DataContext="{d:DesignInstance local:WeaponUserControlViewModel}"
        Height="700" Width="730" FlowDirection="RightToLeft" Loaded="UserControl_Loaded" >
<AdornerDecorator>
    <Expander  IsExpanded="True" >
        <DockPanel>
            <WrapPanel DockPanel.Dock="Top"   DataContext="{Binding Path=SelectedWeapon}">
                <StackPanel Width="315" Margin="20,0,10,0">

                    <ComboBox x:Name="CmbWeaponType" IsReadOnly="True" IsEditable="True"
                          ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, 
                          AncestorType={x:Type UserControl}}, Path=DataContext.WeaponTypeList,ValidatesOnNotifyDataErrors =True,ValidatesOnDataErrors=True,
                    NotifyOnValidationError=True,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="weaponTypeName" SelectedValuePath="ID" >
                        <ComboBox.SelectedValue>
                            <Binding Path="weaponTypeID" Mode="TwoWay" 
                                 UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True" NotifyOnValidationError="True">
                            </Binding>
                        </ComboBox.SelectedValue>
                    </ComboBox>
                </StackPanel>
                <StackPanel Width="315" Margin="20,0,10,0" >

                    <TextBox x:Name="TxtWeaponNumber" Width="315" Text="{Binding weaponNumber,UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True ,ValidatesOnNotifyDataErrors=True,ValidatesOnDataErrors=True,NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True,ValidatesOnExceptions=True}"  >
                        <!--<TextBox.Text>
                            <Binding Path="weaponNumber">
                                <Binding.ValidationRules >
                                    <ad:RequiredRule ValidatesOnTargetUpdated="True"  />
                                </Binding.ValidationRules>
                            </Binding>
                        </TextBox.Text>-->
                    </TextBox>
                </StackPanel>
                <StackPanel Width="315" Margin="20,0,10,0">

                    <TextBox x:Name="TxtOwnership" Width="315"
                         controls:TextBoxHelper.IsWaitingForData="True"
                         Text="{Binding Path=ownership}" />
                </StackPanel>
                <StackPanel Width="315" Margin="20,0,10,0">

                    <TextBox x:Name="TxtMagazineNumber" Width="315"
                         controls:TextBoxHelper.IsWaitingForData="True"
                         Text="{Binding Path=magazineNumber}" />
                </StackPanel>
                <StackPanel>

                    <TextBox x:Name="TxtNotes" Margin="20,0,10,0" Width="660" Height="100"
                         controls:TextBoxHelper.IsWaitingForData="True" Text="{Binding Path=note}" />
                </StackPanel>
                <StackPanel Width="660" Margin="10,10,10,0">
                    <TextBlock Text="{Binding AllErrors}"  Foreground="Red" >

                    </TextBlock>
                </StackPanel >


            </WrapPanel>
            <DataGrid x:Name="DgvWeapons" Margin="0,10,0,10" VerticalContentAlignment="Center"  ItemsSource="{Binding WeaponsList, Mode=OneWay,ValidatesOnNotifyDataErrors=False,NotifyOnValidationError=False}"  
                  HorizontalContentAlignment="Center" IsReadOnly="True"  AlternatingRowBackground="{DynamicResource AccentColorBrush4}" SelectionMode="Single" 
                  CanUserDeleteRows="False" CanUserAddRows="False" AutoGenerateColumns="False" Width="657"  SelectedItem="{Binding SelectedWeapon,ValidatesOnNotifyDataErrors=False,NotifyOnValidationError=False}" MouseLeftButtonDown="DgvWeapons_MouseLeftButtonDown">
                <DataGrid.Columns>
                    <DataGridTextColumn Width="100" Binding="{Binding Path=WeaponTypeName}" />
                    <DataGridTextColumn  Width="100" Binding="{Binding Path=weaponNumber}"/>
                    <DataGridTextColumn  Width="100" Binding="{Binding Path=ownership}"/>
                    <DataGridTextColumn  Width="100" Binding="{Binding Path=magazineNumber}"/>
                    <DataGridTextColumn  Width="100" Binding="{Binding Path=note}"/>
                </DataGrid.Columns>
            </DataGrid>
        </DockPanel>
    </Expander>
</AdornerDecorator>
</UserControl>
下面是实现代码

    public string Error
    {
        get {return string.Empty; }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "weaponNumber")
            {
                bool valid = !string.IsNullOrEmpty(weaponNumber);

                if (!valid)
                {
                    var propertyErrors = new List<string>();
                    propertyErrors.Add("error message");
                    SetErrors("weaponNumber", propertyErrors);
                    return "error message";
                }
                else
                {
                    ClearErrors("weaponNumber");
                }
                OnPropertyChanged("AllErrors");
            }

            if (columnName == "weaponTypeID")
            {
                bool valid = weaponTypeID != null && weaponTypeID != new Guid();

                if (!valid)
                {
                    var propertyErrors = new List<string>();
                    propertyErrors.Add("error message");
                    SetErrors("weaponTypeID", propertyErrors);
                }
                else
                {
                    ClearErrors("weaponTypeID");
                }
                OnPropertyChanged("AllErrors");
                return "error message";
            }

            return null;
        }
    }
公共字符串错误
{
获取{return string.Empty;}
}
公共字符串此[string columnName]
{
得到
{
如果(列名称=“武器编号”)
{
bool valid=!string.IsNullOrEmpty(武器编号);
如果(!有效)
{
var propertyErrors=新列表();
添加(“错误消息”);
设置错误(“武器编号”,属性错误);
返回“错误消息”;
}
其他的
{
明确错误(“武器编号”);
}
不动产变更(“所有错误”);
}
如果(columnName==“weaponTypeID”)
{
bool valid=weaponTypeID!=null&&weaponTypeID!=new Guid();
如果(!有效)
{
var propertyErrors=新列表();
添加(“错误消息”);
设置错误(“weaponTypeID”,propertyErrors);
}
其他的
{
ClearErrors(“weaponTypeID”);
}
不动产变更(“所有错误”);
返回“错误消息”;
}
返回null;
}
}

如果您对
IDataErrorInfo
有问题,您不认为显示相关的实现代码是一个好主意吗?我编辑了文章并添加了实现我也有同样的问题。解决了吗?试着拿出一个最小的复制样本。很难帮助w/o复制。请注意,大多数验证问题都源于错误存储在对象中这一事实,而应该根据需要计算错误。在这里检查我的答案:
    public string Error
    {
        get {return string.Empty; }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "weaponNumber")
            {
                bool valid = !string.IsNullOrEmpty(weaponNumber);

                if (!valid)
                {
                    var propertyErrors = new List<string>();
                    propertyErrors.Add("error message");
                    SetErrors("weaponNumber", propertyErrors);
                    return "error message";
                }
                else
                {
                    ClearErrors("weaponNumber");
                }
                OnPropertyChanged("AllErrors");
            }

            if (columnName == "weaponTypeID")
            {
                bool valid = weaponTypeID != null && weaponTypeID != new Guid();

                if (!valid)
                {
                    var propertyErrors = new List<string>();
                    propertyErrors.Add("error message");
                    SetErrors("weaponTypeID", propertyErrors);
                }
                else
                {
                    ClearErrors("weaponTypeID");
                }
                OnPropertyChanged("AllErrors");
                return "error message";
            }

            return null;
        }
    }