Reputation: 3409
so I have one example that is working here:
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors), Converter={StaticResource ValidationConverter}}"
/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value="GraphPenWidth" />
<Setter Property="Background"
Value="Blue"
/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
<TextBox.Text>
<Binding Path="GraphPenWidth" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<DaedalusValidationRules:IntegerValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
However, is there any way to use a validation rule without binding to a datacontext?
I am trying to make a generic dialogbox that I can pass various validation rules to. However, I found after a while that even when I create the validation rule in xaml it wasn't working correctly. I had read that I could just bind the TextBox's Text Property to itself, but this did not work.
However, when I put a breakpoint in the ValidationRule it seems to be getting called at the correct point when I insert data. In addition the style appears to be working because the background is blue. That leads me to believe that Validation.HasError is never becoming true or is becoming true and changing back so fast that I can't see the change.
The validation rule gets called after every letter I type, yet the textbox doesn't update to show haserror = true. why is this?
Am I just not allowed to bind a property to itself? is there any other way I can use a validation rule without having a binding or do I just always have to create an extra property to bind to? The shortest fix is just to create an extra text property and bind it pointlessly, but I had hoped that wasn't necessary.
<TextBox
Margin="3"
Height="25"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
Grid.Column="1"
x:Name="MainTextBox"
>
<TextBox.Text>
<Binding RelativeSource="{RelativeSource Self}" Path="Text" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<rules:IntegerValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors), Converter={StaticResource ValidationConverter}}"
/>
<Setter Property="Background"
Value="Red"
/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value="Default Signal Height Percentage" />
<Setter Property="Background"
Value="Blue"
/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
So I actually managed to get the validation working in xaml by just making a property to bind against called Text on the GenericDialogBox and then binding that Text property to the Text Property of the Textbox. However, I can't seem to get the same code to work in the code behind.
<TextBox.Text>
<Binding Path="Text" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<rules:IntegerValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
but when i try this in the code behind, it doesn't work.
Binding myBinding = new Binding();
myBinding.Source = this;
myBinding.Path = new PropertyPath("Text");
myBinding.NotifyOnValidationError = true;
myBinding.NotifyOnSourceUpdated = true;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myBinding.ValidationRules.Add(rule);
MainTextBox.SetBinding(TextBlock.TextProperty, myBinding);
what am I missing?
Upvotes: 5
Views: 10765
Reputation: 3409
Gave up on binding from code behind, i create a binding to a property in the xaml, and then in the constructor's code behind, I take the validation rule passed to the constructor and add it to the validation rules like so:
public GenericDialogBox(string MainLabelContent, string WindowTitle, string TextboxDefaultText, ValidationRule rule)
{
this.DataContext = this;
Text = "";
if (rule != null)
{
TextBoxValidationRule = rule;
}
InitializeComponent();
MainLabel.Content = MainLabelContent;
Title = WindowTitle;
Binding binding = BindingOperations.GetBinding(MainTextBox, TextBox.TextProperty);
binding.ValidationRules.Add(rule);
MainTextBox.SelectAll();
MainTextBox.Focus();
}
Upvotes: 1
Reputation: 22702
Try set for your Binding NotifyOnValidationError
to True
, by default it is False:
Gets or sets a value that indicates whether the
BindingValidationError
event is raised on validation errors.
Example:
<Binding NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" ... />
Also you can see the ValidatesOnDataErrors
property, he is used when your ViewModel
implement the IDataErrorInfo
interface.
Upvotes: 4