0
votes

My simple program has two windows:

  • from the first one I set a Boolean value, which then...
  • I'll use in the second window to disable a number of TextBoxes depending on the aforementioned value itself.

Said TextBoxes are also characterized by a validation binding. At now my validation task is flawlessly working, but I'm not able to make the binding to the IsEnabled TextBox property work.

This is the snippet of my XAML containing one of the TextBoxes (for now the only one I've bound):

<TextBox x:Name="tbSlave1" Validation.Error="ValidationError" IsEnabled="{Binding TextBoxEnabled}" Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=SlavePoint1Name, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"/>

While this is my second window class:

public partial class GeneratorWindow : Window, INotifyPropertyChanged
{
    private readonly Validator validator = new Validator();

    private int noOfErrorsOnScreen;

    public GeneratorWindow()
    {
        this.InitializeComponent();
        this.grid.DataContext = this.validator;
    }

    public int NumberOfPoints { private get; set; }

    public int MainPDC { private get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    private Boolean IsEnabled;
    public Boolean TextBoxEnabled
    {
        get { return IsEnabled; }

        set
        {
            IsEnabled = value;
            NotifyPropertyChanged("TextBoxEnabled");
        }
    }

    private void ValidationError(object sender, ValidationErrorEventArgs eventArgs)
    {
        if (eventArgs.Action == ValidationErrorEventAction.Added)
        {
            this.noOfErrorsOnScreen++;
        }
        else
        {
            this.noOfErrorsOnScreen--;
        }
    }

    private void ValidationCanBeExecuted(object sender, CanExecuteRoutedEventArgs eventArgs)
    {
        eventArgs.CanExecute = this.noOfErrorsOnScreen == 0;
        eventArgs.Handled = true;
    }

    private void ValidationExecuted(object sender, ExecutedRoutedEventArgs eventArgs)
    {
        // If the validation was successful, let's generate the files.
        this.Close();

        eventArgs.Handled = true;
    }
}

For now, what I'm getting back is that my window is disabled (can't select any TextBox) and, obviously, this:

System.Windows.Data Error: 40 : BindingExpression path error: 'TextBoxEnabled' property not found on 'object' ''Validator' (HashCode=14499481)'. BindingExpression:Path=TextBoxEnabled; DataItem='Validator' (HashCode=14499481); target element is 'TextBox' (Name='tbSlave1'); target property is 'IsEnabled' (type 'Boolean')

From what I can understand, the culprit is the way I'm managing the DataContext in my class constructor. I probably need to add something to the validator line or totally change it, but I can't understand how.

1
{Binding TextBoxEnabled} uses the current DataContext as its source object, which obviously has no TextBoxEnabled property (which is clearly said by the error message). You need to specify the window as source object, e.g. by setting the Binding's ElementName or RelativeSource. - Clemens
Please show your Validator class (and see TextBoxEnabled is missing) - Stefan
@Clemens, should I use the RelativeSource similarly to this {Binding Path=TextBoxEnabled, RelativeSource={RelativeSource Self}}? - Davide3i
Not Self, but AncestorType=Window. - Clemens
Ok, it does work. Thank you. - Davide3i

1 Answers

0
votes

I think you should be fine if you set the DataContext to the GeneratorWindow and updated you bindings accordingly. For that to work you need to change Validator to a public property.

Changed Validator definition:

public Validator Validator { get; } = new Validator();

DataContext:

this.grid.DataContext = this;

Updated Binding:

<TextBox x:Name="tbSlave1" 
         Validation.Error="ValidationError" 
         IsEnabled="{Binding TextBoxEnabled}" 
         Text="{Binding UpdateSourceTrigger=PropertyChanged, 
                        Path=Validator.SlavePoint1Name, 
                        ValidatesOnDataErrors=true, 
                        NotifyOnValidationError=true}"/>