I try to create a textbox which have multi level validation, so notify the user if there is some fields which should be filled but not required. I created a control, which is works really good, I only have one problem. I want to use this new textbox in an other usercontrol. I have a save button there, and I want this button to be enabled when this textbox has no validation error, but it seems the validation error is inside my custom texbox control, so the button is always enabled. Here is the control xaml code:
MultiLevelValidationTextBox.xaml
<Style x:Key="MultiLevelValidationTextBoxStyle" TargetType="local:MultiLevelValidationTextBoxControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MultiLevelValidationTextBoxControl">
<Grid>
<Grid.Resources>
<local:IsNullConverter x:Key="IsNullConverter" />
</Grid.Resources>
<TextBox
x:Name="PART_TextBox"
Text="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" Value="#fcba03" />
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=Required, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True">
<Setter Property="Text">
<Setter.Value>
<Binding Path="BindingText" RelativeSource="{RelativeSource Mode=TemplatedParent}" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<local:TextBoxTextValidation ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Polygon x:Name="PART_Polygon" Points="0,0 5,0 0,5 0,0" Margin="0,3,2,0" HorizontalAlignment="Right" FlowDirection="RightToLeft" ToolTip="A mező kitöltése ajánlott!">
<Polygon.Style>
<Style TargetType="Polygon">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="#fcba03" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="Transparent" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="Transparent" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Polygon.Style>
</Polygon>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is the MultiLevelValidationTextBoxControl.cs
[TemplatePart(Name = PART_TextBox, Type = typeof(TextBox))]
[TemplatePart(Name = PART_Polygon, Type = typeof(Polygon))]
public class MultiLevelValidationTextBoxControl : TextBox
{
private const string PART_TextBox = "PART_TextBox";
private const string PART_Polygon = "PART_Polygon";
private TextBox _textBox = null;
private Polygon _polygon = null;
static MultiLevelValidationTextBoxControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiLevelValidationTextBoxControl), new FrameworkPropertyMetadata(typeof(MultiLevelValidationTextBoxControl)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_textBox = GetTemplateChild(PART_TextBox) as TextBox;
_polygon = GetTemplateChild(PART_Polygon) as Polygon;
}
public static readonly DependencyProperty RequiredProperty = DependencyProperty.Register("Required", typeof(bool), typeof(MultiLevelValidationTextBoxControl), new UIPropertyMetadata(false));
public bool Required
{
get
{
return (bool)GetValue(RequiredProperty);
}
set
{
SetValue(RequiredProperty, value);
}
}
public static readonly DependencyProperty RecommendedProperty = DependencyProperty.Register("Recommended", typeof(bool), typeof(MultiLevelValidationTextBoxControl), new UIPropertyMetadata(false));
public bool Recommended
{
get
{
return (bool)GetValue(RecommendedProperty);
}
set
{
SetValue(RecommendedProperty, value);
}
}
public static readonly DependencyProperty BindingTextProperty = DependencyProperty.Register("BindingText", typeof(string), typeof(MultiLevelValidationTextBoxControl), new UIPropertyMetadata(string.Empty));
public string BindingText
{
get
{
return (string)GetValue(BindingTextProperty);
}
set
{
SetValue(BindingTextProperty, value);
}
}
public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText", typeof(string), typeof(MultiLevelValidationTextBoxControl), new UIPropertyMetadata(string.Empty));
public string LabelText
{
get
{
return (string)GetValue(LabelTextProperty);
}
set
{
SetValue(LabelTextProperty, value);
}
}
}
And I have an other window, where I want to use this, and there is a button which should be disabled if the texbox is required:
<Button
Grid.Row="1"
Grid.Column="6"
Margin="10,0,0,0"
MinWidth="80"
Height="30">
So is there any way to pass the validation errors to the parent? Everything is works fine, only this part fails.
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=CustomTextBoxName, Path=(Validation.HasError), UpdateSourceTrigger=PropertyChanged}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
Save
</Button>