0

I have a class Client :

public class Client : INotifyPropertyChanged
{

    private string m_strCode;
    public string strCode
    {
        get { return m_strCode; }
        set
        {

            if (CodeIsValide(strCode))
            {                  
                m_strCode = value;
                FirePropertyChangedEvent("strCode");

            }
            else
            {
                throw new ApplicationException("bad Data !");
            }

            FirePropertyChangedEvent("strCode");

        }
    }

    private string m_strName;
    public string strName
    {
        get { return m_strName; }
        set
        {

            if (NameIsValide(strName))
            {
                m_strName = value;
                FirePropertyChangedEvent("strName");

            }
            else
            {
                throw new ApplicationException("Bad Data! ");
            }

            FirePropertyChangedEvent("strName");

        }
    }

    public Client(string Code, string Name)
    {
        strCode = Code;
        strName = Name;
    }

    public Client()
    {

    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void FirePropertyChangedEvent(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

On my WPF Window, i have two textbox : on for client.strCode, and the other for client.strNom.

Here is the XAML :

<TextBox x:Name="TextBox_Code"
         HorizontalAlignment="Left"
         Height="25"
         Margin="106,230,0,0"
         TextWrapping="Wrap"
         VerticalAlignment="Top"
         Width="78">
  <TextBox.Text>
    <Binding Path="strCode"
             UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

<TextBox x:Name="TextBox_Name"
         HorizontalAlignment="Left"
         Height="25"
         Margin="106,230,0,0"
         TextWrapping="Wrap"
         VerticalAlignment="Top"
         Width="78">
  <TextBox.Text>
    <Binding Path="strName"
             UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

The data input are verifiyng with the ValidationProcess. If the validation is false, it appear a warning label near the textbox.

My problem is : If i load bad data ( from a DataBase) to a Collection of Client object. The load use the set() of my strCode and strName, and, if the data are bad, the ExceptionValidationRule cannot be throwing ( I think it's because the ExceptionValidationRule is not invoked from the textbox binded). ( I'm not English, it's not esay to explain sorry).

I think i need to specify when i want to invoke the verifiy process.

Anyone have advices please ?

If anyone want, i create a sample VS project in order to share my problem.

EDIT : If i use a Custom Validator class, it OK !

Just a question, in order to force the validation test, i need to do this, when i select the line in my DataGrid :

    private void myDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
    {
        // Affiche le code évt sélectionné dans le tableau, dans les champs modifiable ( en haut de l'écran )

        var item = myDataGrid.SelectedItem as Client;
        if ((item != null))
        {
            TextBox_Code.Text = item.strCode;
            TextBox_Name.Text = item.strName;
        }
    }

:

TextBox_Code.Text = item.strCode;
TextBox_Name.Text = item.strName;

If i remove this two line, the textbox are corectly initialized because of the binding, but the validation process is not invoked. Why ? Is there a way to force the the validation process and use the full binding whitout :

TextBox_Code.Text = item.strCode;
TextBox_Name.Text = item.strName;

Thanks :)

Thanks a lot :)

Best regards,

Nixeus :)

4

1 回答 1

1

好吧,如果我正确理解您的要求,

如果属性是从 xaml 视图之外的任何内容设置的,您不希望引发异常。

我首选的解决方案是根本不使用,而是ExceptionValidationRule更喜欢 Custom ValidationRule。这将解决您的问题。示例展示了如何创建和使用这样的功能。

自定义验证规则示例:

public class CodeRangeRule : ValidationRule {
  public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
    int strCode = -1;
    if (value != null && !Int32.TryParse(value.ToString(), out strCode))
      return new ValidationResult(false, "Illegal strCode");
    if (strCode < 9999 && strCode > 0) // Modify to suit your Validity Conditions
      return new ValidationResult(true, null);
    return new ValidationResult(false, "strCode is not within acceptable code range");
  }
}

和你的xml:

<TextBox x:Name="TextBox_Code" HorizontalAlignment="Left" Height="25" Margin="106,230,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="78">
    <TextBox.Text>
        <Binding Path="strCode"  UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <local:CodeRangeRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

或者

如果您出于某种原因不想使用自定义ValidationRule,您可以ExceptionValidationRule在视图中保持原样,并在从数据库加载调用 setter 或在您的

public class Client : INotifyPropertyChanged

添加另一个属性(例如带有 values 的枚举kDatabaseLoadkView以指示对象是否由视图/数据库处理。因此,在你的设置器中strCode检查strName这个枚举是否kView在抛出你的异常之前。

现在,当您执行数据库加载并创建对象时,在设置和之前Client将其分配给枚举。确保将枚举切换回加载完成后。kDatabaseLoadstrNamestrCodekView

于 2013-04-18T09:45:28.930 回答