1

I have this template for an itemscontrol:

<DataTemplate DataType="{x:Type models:StringParameter}">
         <TextBox materialDesign:HintAssist.Hint="{Binding Name}">
             <TextBox.Text>
                 <Binding Path="Value">
                     <Binding.ValidationRules>
                         <ınteractiveCode:NotEmptyValidationRule ValidatesOnTargetUpdated="True"></ınteractiveCode:NotEmptyValidationRule>
                     </Binding.ValidationRules>
                 </Binding>
             </TextBox.Text>
         </TextBox>
     </DataTemplate>

And I have a button that works with a command, I want it to get enabled when all validations are met in ItemsControl. But I can't find a way to reach textboxes which are inside data templates.

Talha Talip Açıkgöz
  • 1,821
  • 4
  • 15
  • 28

1 Answers1

1

I have a simple approach to solve this specific issue. I have created a ValidationChecker class that will check for existence of validation errors using IsValid method.

public class ValidationChecker : Freezable
{
    public static List<DependencyObject> elements = new List<DependencyObject>();

    public static int GetValidationObject(DependencyObject obj)
    {
        return (int)obj.GetValue(ValidationObjectProperty);
    }

    public static void SetValidationObject(DependencyObject obj, int value)
    {
        obj.SetValue(ValidationObjectProperty, value);
    }

    // Using a DependencyProperty as the backing store for ErrorCount.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValidationObjectProperty =
        DependencyProperty.RegisterAttached("ValidationObject", typeof(DependencyObject), typeof(ValidationChecker), new PropertyMetadata(null, OnValueChanged));


    public static bool IsValid()
    {
        foreach (var item in elements)
        {
            if (Validation.GetHasError(item)) return false;
        }
        return true;
    }

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        elements.Add(d);
    }

    protected override Freezable CreateInstanceCore()
    {
        return new ValidationChecker();
    }
}

ValidationObject attached property can be implemented as like below

<DataTemplate>
    <TextBox local:ValidationChecker.ValidationObject="{Binding RelativeSource={RelativeSource Self}}">
         <TextBox.Text>
             <Binding Path="Value">
                 <Binding.ValidationRules>
                      <local:NotEmptyValidationRule ValidatesOnTargetUpdated="True"></local:NotEmptyValidationRule>
                 </Binding.ValidationRules>
              </Binding>
          </TextBox.Text>
       </TextBox>
</DataTemplate>

You have already mentioned that your Button has been bind to a Command. So implement CanExecute method for the Command and call ValidationChecker.Isvalid(). Don't forget to invoke RaiseCanExecute method for this Command whenever you need.

Vimal CK
  • 3,543
  • 1
  • 26
  • 47
  • It seems like a good approach, but will this work when text box gets removed? – Talha Talip Açıkgöz Oct 22 '17 at 21:14
  • I've tested it, it is pretty much what I want, thanks. But it does not work when textboxes get removed, how do we handle that? EDIT: I handled the unload event of the textbox to remove itself from the list. This the correct answer now. – Talha Talip Açıkgöz Oct 23 '17 at 15:11