How to successfully implement WPF textbox validation? - c#

I'm trying to implement what should be simple textbox validation for a WPF application, but I'm having some problems.
I used this guide: http://www.codeproject.com/Tips/690130/Simple-Validation-in-WPF
My textbox in MainWindow.xaml:
<TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="23"
Margin="93,111,0,0" TextWrapping="Wrap" VerticalAlignment="Top"
Width="120" Style="{StaticResource textBoxInError}"
Validation.ErrorTemplate="{StaticResource validationErrorTemplate}">
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:NameValidator/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
My NameValidator Class in MainWindow.xaml.cs:
public class NameValidator : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value == null)
return new ValidationResult(false, "value cannot be empty.");
else
{
if (value.ToString().Length > 3)
return new ValidationResult(false, "Name cannot be more than 3 characters long.");
}
return ValidationResult.ValidResult;
}
}
My Static Resources in App.xaml:
<ControlTemplate x:Key="validationErrorTemplate">
<DockPanel>
<TextBlock Foreground="Red" DockPanel.Dock="Top">!</TextBlock>
<AdornedElementPlaceholder x:Name="ErrorAdorner"></AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
<Style x:Key="textBoxInError" 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)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
I can run the application without any errors, but the validation is never triggered.

Using what you posted, it works fine for me, it produces the red "!" above the textbox. However, I DID remember to set my DataContext, ie.
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
Without this, it won't work.

Related

Binding TextBoxes to a Button (MVVM)

I'm making an application to generate recipes for a specified period (for example a week). As part of this application I have to make a list of ingredients. These ingredients can be specified by the user so I made a UserControl for adding an ingredient. This UserControl contains 6 TextBox-es and a Button. What I'm trying to do is when the user click on the button, the ingredient specified by the user (and by the TextBoxes) will be added to the list of ingredients.
I'm using MVVM architecture and a MultiValueConverter to bind the TextBoxes to the Button. I noticed that the Convert method was called only at the instantiation, but not when I click the Button.
How can I solve this problem still using MVVM?
Thanks for your advice and time!
The corresponding code snippets:
AddIngredientView.xaml:
<UserControl.Resources>
<ResourceDictionary>
<converters:IngredientConverter x:Key="IngredientConverter"/>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel>
<TextBlock Text="Étel hozzáadása" Foreground="White" FontSize="28" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20"/>
<TextBox Name="nameTextBox" ToolTip="Név" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<TextBox Name="weightTextBox" ToolTip="Tömeg (g)" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<TextBox Name="energyTextBox" ToolTip="Energia (kcal)" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<TextBox Name="carbohydrateTextBox" ToolTip="Szénhidrát (g)" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<TextBox Name="proteinTextBox" ToolTip="Fehérje (g)" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<TextBox Name="fatTextBox" ToolTip="Zsír (g)" Width="250" Height="40" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="5" Style="{StaticResource ModernTextbox}"/>
<Button Content="További értékek" Foreground="#353340" FontSize="14" Margin="0,10,60,0">
<Button.Style>
<Style TargetType="Button">
<Setter Property="TextElement.FontFamily" Value="Fonts/#Poppins"/>
<Setter Property="Background" Value="DarkGray"/>
<Setter Property="Cursor" Value="Hand"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#353340"/>
<Setter Property="Foreground" Value="DarkGray"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Width="130" Height="25" CornerRadius="12" Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Button Content="Hozzáadás" Foreground="#353340" FontSize="14" Margin="500,50,0,0" Command="{Binding AddIngredientCommand}">
<Button.Style>
<Style TargetType="Button">
<Setter Property="TextElement.FontFamily" Value="Fonts/#Poppins"/>
<Setter Property="Background" Value="DarkGray"/>
<Setter Property="Cursor" Value="Hand"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#353340"/>
<Setter Property="Foreground" Value="DarkGray"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Width="100" Height="25" CornerRadius="12" Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource IngredientConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="Text" ElementName="nameTextBox"/>
<Binding Path="Text" ElementName="weightTextBox"/>
<Binding Path="Text" ElementName="energyTextBox"/>
<Binding Path="Text" ElementName="carbohydrateTextBox"/>
<Binding Path="Text" ElementName="proteinTextBox"/>
<Binding Path="Text" ElementName="fatTextBox"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</StackPanel>
IngredientConverter.cs:
public class IngredientConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return String.Concat(values[0], ",", values[1], ",", values[2], ",", values[3], ",", values[4], ",", values[5]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return (value as string).Split(',');
}
}
AddIngredientViewModel.cs:
public class AddIngredientViewModel : ViewModelBase
{
#region Fields
private YazioRecipesAddOnModel _model;
#endregion
#region Properties
public DelegateCommand AddIngredientCommand { get; private set; }
#endregion
#region Constructor
public AddIngredientViewModel(YazioRecipesAddOnModel model)
{
_model = model;
AddIngredientCommand = new DelegateCommand(param => AddIngredient(param.ToString()));
}
#endregion
#region Public methods
public void AddIngredient(String ingredientString)
{
if (ingredientString == null)
return;
_model.AddIngredient(ingredientString);
}
#endregion
}
You should bind each TextBox to a different source property of the view model e.g.:
<TextBox Name="weightTextBox" Text="{Binding Weight}" />
You could then simply access the values directly in your AddIngredient method:
string ingredientString = string.Concat(this.Weight, "," ...);
_model.AddIngredient(ingredientString);
One of the key aspects of MVVM is to implement the application logic in the view models. Don't use converters for this.

Input Validation in TextBox

Don't want the error message to be displayed at start/as tab opens.
Validation is implemented using IDataErrorInfo (to VM), an ErrorTemplate (XAML) is defined and able to get error message beside TextBox.
VM:(extended IDataErrorInfo)
public string this[string propertyName]
{
get
{
string validationResult = null;
switch (propertyName)
{
case "ProjectManager":
validationResult = ValidateManagerName();
break;
}
return validationResult;
}
}
public string ValidateManagerName()
{
if (string.IsNullOrEmpty(this.ProjectManager))
{
return "Manager name is mandatory!";
}
else
return string.Empty;
}
XAML.cs
save_option_summ()
{
BindingExpression be3 = managername.GetBindingExpression(TextBox.TextProperty);
be3.UpdateSource();
}
<StackPanel.Resources>
<ControlTemplate x:Key="ErrorTemplate">
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right" Foreground="Blue" FontSize="13" Text="{Binding ElementName=adorned,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" >
</TextBlock>
<Border BorderBrush="Red" BorderThickness="2">
<AdornedElementPlaceholder x:Name="adorned"/>
</Border>
</DockPanel>
</ControlTemplate>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="Project Manager" FontSize="14" Margin="100,0,0,0" Width="150" FontFamily="Calibri"></Label>
<TextBox Height="auto" Width="300" Background="White" Margin="100,0,0,0" Validation.ErrorTemplate = "{StaticResource ResourceKey=ErrorTemplate}" Name="managername" Text="{Binding ProjectManager,Mode=TwoWay,UpdateSourceTrigger=LostFocus,ValidatesOnDataErrors=True}" TextChanged="TextChanged" FontFamily="Calibri" FontSize="14"/>
</StackPanel>
You should modify the TextBox style so it shows what's wrong with the property. Here is a simple example that shows the error as tooltip:
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors).[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
So, along with shivam sood's (which helps to show error in tooltip) answer.
In code shown above (question),
public string ValidateManagerName()
{
if (string.IsNullOrEmpty(this.ProjectManager))
{
return "string.Empty";
}
//Other conditions can be written like alphanumeric check
else
return string.Empty;
}
Don't return anything in null check (first condition), so that textbox will not always show error message.

How to use a converter for a texblock of a calendar?

I am trying to add a new column in a calendar control to add the week number. I have found a example that works perfect, the problem is very simply and it uses code behind, and I am wanted to use MVVM and a converter in another class, no inside the code behind.
Then example that I have found is this:
<Window x:Class="CalendarioNumeroSemana.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CalendarioNumeroSemana"
xmlns:app="clr-namespace:CalendarioNumeroSemana"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Calendar Grid.IsSharedSizeScope="True" HorizontalAlignment="Left" Margin="209,116,0,0" VerticalAlignment="Top">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="{x:Type CalendarDayButton}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(Grid.Column),RelativeSource={RelativeSource Mode=Self}}"
Value="0">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="XX"/>
<ColumnDefinition SharedSizeGroup="YY"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="0,0,0,0" BorderBrush="Black" Margin="-15,0,0,0">
<TextBlock Margin="0,0,2,0" FontWeight="Bold">
<TextBlock.Text>
<Binding Path="DataContext">
<Binding.Converter>
<app:WeekNumberConverter />
</Binding.Converter>
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="{x:Type CalendarDayButton}"/>
</Binding.RelativeSource>
</Binding>
</TextBlock.Text>
</TextBlock>
</Border>
<TextBlock Text="{Binding }" Grid.Column="1" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
</Window>
namespace CalendarioNumeroSemana
{
/// <summary>
/// Lógica de interacción para MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class WeekNumberConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is DateTime)
{
DateTime dt = (DateTime)value;
return getNumeroSemenaIso8601(dt);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private int getNumeroSemenaIso8601(DateTime paramFecha)
{
System.Globalization.Calendar miCalendario = CultureInfo.InvariantCulture.Calendar;
DateTime miDtFechaBase = paramFecha;
DayOfWeek miDiaSemana = miCalendario.GetDayOfWeek(paramFecha);
if (miDiaSemana == DayOfWeek.Monday) { miDtFechaBase = miDtFechaBase.AddDays(3); }
if (miDiaSemana == DayOfWeek.Tuesday) { miDtFechaBase = miDtFechaBase.AddDays(2); }
if (miDiaSemana == DayOfWeek.Wednesday) { miDtFechaBase = miDtFechaBase.AddDays(1); }
if (miDiaSemana == DayOfWeek.Friday) { miDtFechaBase = miDtFechaBase.AddDays(-1); }
if (miDiaSemana == DayOfWeek.Saturday) { miDtFechaBase = miDtFechaBase.AddDays(-2); }
if (miDiaSemana == DayOfWeek.Sunday) { miDtFechaBase = miDtFechaBase.AddDays(-3); }
return miCalendario.GetWeekOfYear(miDtFechaBase, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
}
}
But I would like to use this in my application, that it uses MVVM and I have the converter to get the week number in another class.
My axml is this:
<Calendar Grid.IsSharedSizeScope="True" HorizontalAlignment="Left" Margin="5,5,5,5" Padding="0,0,0,0" VerticalAlignment="Top">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="{x:Type CalendarDayButton}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(Grid.Column),RelativeSource={RelativeSource Mode=Self}}"
Value="0">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="XX"/>
<ColumnDefinition SharedSizeGroup="YY"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="0,0,0,0" BorderBrush="Black" Margin="-15,0,0,0">
<TextBlock Margin="0,0,2,0" FontWeight="Bold">
<TextBlock.Text>
<Binding Path="DataContext">
<Binding.Converter>
<app:WeekNumberConverter />
</Binding.Converter>
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="{x:Type CalendarDayButton}"/>
</Binding.RelativeSource>
</Binding>
</TextBlock.Text>
</TextBlock>
</Border>
<TextBlock Text="{Binding }" Grid.Column="1" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
My main problem is that I don't know how to change the code of binding.text, and later, in TextBlock Text, it uses Binding, but I don't know what binding is this.
I have tried something like that:
<TextBlock.Text>
<Binding Converter="{StaticResource NumeroSemanaValueConverter}"/>
</TextBlock.Text>
But in the converter I don't get a date, I g et the day of the first button. I need the date.
So how could I adapt the original code to my case?
Thanks.
This has nothing to do with MVVM. It's pure control logic. The template of the control uses a converter to get the week number. A converter is just a class and a template is just a template.
So the example you have found can certainly be used in a MVVM application. It's just a built-in control with a custom template. No view model or logic that should belong to a view model is involved as far as I can see.

How do I bind text of checkbox to Header of Expander

I have an Expander that contains 3 checkbox.
<Expander Header="Bind Here" Grid.Row="3" Grid.ColumnSpan="2">
<StackPanel >
<CheckBox>Test 1</CheckBox>
<CheckBox>Test 2</CheckBox>
<CheckBox>Test 3</CheckBox>
</StackPanel>
</Expander>
I want to append the text of a checked checkbox to the Header of the expander.
Is it possible using binding?
Thanks for the answers but here's what I did:
<Expander Header="{Binding SelectedTitle}" Grid.Row="3" Grid.ColumnSpan="2">
<StackPanel >
<CheckBox IsChecked="{Binding Path=SelectedItem.isTest1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Test 1</CheckBox>
<CheckBox IsChecked="{Binding Path=SelectedItem.isTest2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Test 2</CheckBox>
<CheckBox IsChecked="{Binding Path=SelectedItem.isTest3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Test 3</CheckBox>
</StackPanel>
public String SelectedTitle
{
get
{
StringBuilder builder = new StringBuilder();
if (SelectedItem.isTest1)
builder.Append("Browse subfolders, ");
if (SelectedItem.isTest2)
builder.Append("Enter filename at the panel, ");
if (SelectedItem.isTest3)
builder.Append("Always show scan settings, ");
if (builder.Length == 0)
builder.Append("None");
return builder.ToString().Trim().TrimEnd(',');
}
}
private void SelectedItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
UpdateProperty("SelectedTitle");
}
When your checkbox is checked you need to track if it has been checked or not, you can do this either by binding or event handling or triggers.
Following is a quick example
Using Binding (XAML Only)
if you are keen to have it as binding you can try having triggers and setters on control template for expander like this (I leave it to user to edit and produce a minimal xaml the following piece works but may not be minimal) --
<Window.Resources>
<ControlTemplate x:Key="ControlTemplate" TargetType="Expander">
<Expander x:Name="MyExpander">
<StackPanel Orientation="Vertical">
<CheckBox x:Name="Box1">Test 1</CheckBox>
<CheckBox x:Name="Box2">Test 2</CheckBox>
<CheckBox x:Name="Box3"> Test 3</CheckBox>
</StackPanel>
</Expander>
<ControlTemplate.Triggers>
<Trigger SourceName="Box1" Property="CheckBox.IsChecked" Value="True">
<Setter Property="Header"
TargetName="MyExpander"
Value="{Binding Content, ElementName=Box1 }" />
</Trigger>
<Trigger SourceName="Box2"
Property="CheckBox.IsChecked"
Value="True">
<Setter Property="Header" TargetName="MyExpander"
Value="{Binding Content, ElementName=Box2 }" />
</Trigger>
<Trigger SourceName="Box3"
Property="CheckBox.IsChecked"
Value="True">
<Setter Property="Header"
TargetName="MyExpander"
Value="{Binding Content, ElementName=Box3 }" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Expander Template="{StaticResource ControlTemplate}"/>
or if you don't mind code behind
Code Behind Way
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
var checkBox = ((CheckBox) sender);
if (checkBox.IsChecked != null && checkBox.IsChecked.Value)
{
MyExpander.Header = checkBox.Content.ToString();
}
}
Xaml --
<Expander x:Name="MyExpander">
<StackPanel>
<CheckBox Checked="ToggleButton_OnChecked">Test 1</CheckBox>
<CheckBox Checked="ToggleButton_OnChecked">Test 2</CheckBox>
<CheckBox Checked="ToggleButton_OnChecked">Test 3</CheckBox>
</StackPanel>
</Expander>
Here is a cool way to do so:(Binding + Converter)
XAML:
<Expander Grid.Row="3" Grid.ColumnSpan="2" Name="expander" Width="500">
<Expander.Resources>
<local:ExpanderHeaderConverter x:Key="ExpanderHeaderConverter" />
</Expander.Resources>
<Expander.Header>
<TextBlock >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource ExpanderHeaderConverter}">
<Binding ElementName="c1" Mode="OneWay"/>
<Binding ElementName="c1" Mode="OneWay" Path="IsChecked"/>
<Binding ElementName="c2" Mode="OneWay"/>
<Binding ElementName="c2" Mode="OneWay" Path="IsChecked"/>
<Binding ElementName="c3" Mode="OneWay"/>
<Binding ElementName="c3" Mode="OneWay" Path="IsChecked"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<StackPanel>
<CheckBox Name="c1" >Test 1</CheckBox>
<CheckBox Name="c2">Test 2</CheckBox>
<CheckBox Name="c3">Test 3</CheckBox>
</StackPanel>
</Expander>
Converter:
public class ExpanderHeaderConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string output = string.Empty;
for (int i = 0; i < values.Length; i+=2)
{
if ((values[i + 1] as bool?) == true)
output += (values[i] as CheckBox).Content.ToString()+" ";
}
return output;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Force focus te stay on an ExceptionValidationRule

On a WPF application, i use binding on severals TextBox with ExceptionValidationRule.
I would like to be able to stay on the contrôls which have an ApplicationException whitout leaving it until it have a correct data input. Is there possible ?
Here is my code :
public string strEvtType
{
get { return m_strEvtType; }
set {
m_strEvtType = value;
if (m_objEvtCode.ReadEvtTypebyType(m_strEvtType) != 0)
{
throw new ApplicationException("Error ! : " + m_strEvtType.Trim() + " don't exist");
}
FirePropertyChangedEvent("strEvtType");
FirePropertyChangedEvent("m_objEvtCode.strDes");
}
My xaml :
<TextBox Name="TextBox_TypeEvenement" Grid.Column="1" VerticalAlignment="Center" Height="20" LostFocus="TextBox_TypeEvenement_LostFocus">
<TextBox.Text>
<Binding Path="strEvtType">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
My Template
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="False">
<TextBlock DockPanel.Dock="Right"
Foreground="red"
FontSize="9pt"
Text="{Binding ElementName=MyAdorner,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="MyAdorner" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
Thanks a lot :)
Best regards,
Nixeus

Categories