Custom validation of textbox in WPF - wpf

So I'm trying to do something along this example: http://www.codeproject.com/KB/WPF/wpfvalidation.aspx
My Textbox currently looks like this:
<TextBox Height="23" HorizontalAlignment="Left" Margin="118,60,0,0" Name="CreateUserCPRTextbox" VerticalAlignment="Top" Width="120" >
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="LostFocus">
<Binding.ValidationRules>
<validators:TextRangeValidator
MinimumLength="10"
MaximumLength="10"
ErrorMessage="ID has to be 10 letters" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
I've directly copied my TextRangeValidator from the example on that website. Nothing happens when I lose focus on the textbox. No matter what I type in it. Any Ideas? :)

Have you set the Validation.ErrorTemplate? It is defined as below in the Application.Resources in the example.You may have missed that
<Application.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right"
Foreground="Orange"
Margin="5"
FontSize="12pt"
Text="{Binding ElementName=MyAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</TextBlock>
<Border BorderBrush="Green" BorderThickness="3">
<AdornedElementPlaceholder Name="MyAdorner" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<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>
</Application.Resources>
EDIT
Your default value is not triggering the validation routine.To force it to validate for default value you have to set
<validators:TextRangeValidator ValidatesOnTargetUpdated="True"
MinimumLength="10"
MaximumLength="10"
ErrorMessage="ID has to be 10 letters" />

I think you need to set ValidatesOnDataErrors=True in binding for Text to make it work

WPF TextBox Validation
<Style x:Key="TextBoxInError" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Grid>
<Polygon Points="20,10,20,0 0,0"
Stroke="Black"
StrokeThickness="1"
Fill="Red"
HorizontalAlignment="Right"
VerticalAlignment="Top"
ToolTip="{Binding ElementName=adorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
<AdornedElementPlaceholder x:Name="adorner"/>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</Grid>
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0"
Width="150" Height="20" CornerRadius="5"
ToolTip="{Binding ElementName=customAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text= "{Binding ElementName=customAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" VerticalAlignment="center" HorizontalAlignment="Left"
FontWeight="Bold" Foreground="white" Width="250" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<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>

Related

WPF nested template binding in itemscontrol

I have a problem with nested template bindings.
Having an ItemsControl with a template, which works great. This template contains a tooltip as well (which shows perfectly).
<Button.ToolTip>
<TextBlock Text="{Binding Path=DetailPaneText}" />
</Button.ToolTip>
But inside the itemscontrol template, I have a ToggleButton with another template inside it. And I can't seem to show the text over there as well since the binding isn't correct.
Code inside the toggle button
<StackPanel Background="#293344" Width="200" x:Name="DetailTab" Margin="0">
<TextBlock FontSize="12" Text="" Foreground="White" />
</StackPanel>
What kind of binding or syntax should I put in between the Text tags? I tried several options but none of them seemed to work yet. Currently out of guesses.
Thanks
Complete code snippet
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0" >
<Button Command="{x:Static CobraInfrastructure:Commands.NavigateFromBreadcrumb}" CommandParameter="{Binding Path=Current}" Tag="{Binding DetailPaneText}" x:Name="TextBlock_Detail" Style="{DynamicResource BreadcrumbButton}">
<Button.Resources>
<Style BasedOn="{StaticResource {x:Type ToolTip}}" TargetType="ToolTip">
<Setter Property="Background" Value="#F8F8F8" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Padding" Value="15" />
<Setter Property="MinWidth" Value="300" />
<Setter Property="MinHeight" Value="150" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
</Button.Resources>
<Button.ToolTip>
<TextBlock Text="{Binding Path=DetailPaneText}" />
</Button.ToolTip>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="HyphenTextBlock" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding Path=EntityTitle}" FontSize="12" FontWeight="Bold" Foreground="White" Grid.Row="0" Grid.Column="0"/>
<TextBlock VerticalAlignment="Stretch" Text="{Binding Path=Text, NotifyOnTargetUpdated=True, Mode=OneWay}" FontSize="10" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/>
</Grid>
</Button>
<ToggleButton Focusable="False" Style="{DynamicResource BreadcrumbOpenButton}" VerticalAlignment="Stretch" HorizontalAlignment="Center" Tag="{Binding Path=DetailPaneText}">
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<StackPanel Orientation="Horizontal">
<Border Width="13" Background="#293344">
<fa:FontAwesome Icon="CaretRight" Foreground="White" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<StackPanel Background="#293344" Width="200" x:Name="DetailTab" Margin="0">
<TextBlock FontSize="12" Text="" Foreground="White" />
</StackPanel>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Width" TargetName="DetailTab" Value="200"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Width" TargetName="DetailTab" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding IsOverview}" Value="True">
<Setter Property="Style" TargetName="TextBlock_Detail" Value="{DynamicResource LinkButton}" />
<Setter Property="FontWeight" TargetName="TextBlock_Detail" Value="Bold" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
You should reference on TemplatedParent in Binding:
<StackPanel Background="#293344" Width="200" x:Name="DetailTab" Margin="0">
<TextBlock FontSize="12" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.DetailPaneText}" Foreground="White" />
</StackPanel>
If you trying to bind a tooltip text of a button to the Text property of textblock, you may bind it using the ElementName.
First name your button using x:Name
<Button x:Name="XButton">
<Button.ToolTip>
<TextBlock Text="{Binding Path=DetailPaneText}" />
</Button.ToolTip>
</Button>
Bind it to text block text using the ElementName.
<StackPanel Background="#293344" Width="200" x:Name="DetailTab" Margin="0">
<TextBlock FontSize="12" Text="{Binding ElementName=XButton, Path=ToolTip.Text}" />
</StackPanel>

Round close button in corner of image

I am creating gallery, it contains images. So I want to remove the images from gallery using close buttons. The position of the close button should be the corner of the every images. How can I create like this corner buttons styles? Any idea?
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="120">
<Button Height="25" VerticalAlignment="Top" Content="Show" Width="100" Margin="5" />
<Image Height="90" Source="{Binding Path=Thumbnail}" MouseLeftButtonDown="Image_MouseLeftButtonDown"/>
<TextBlock TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="{Binding Path=Name}" >
<TextBlock.ToolTip>
<ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource trimmedVisibilityConverter}}">
<ToolTip.Content>
<TextBlock Text="{Binding Name}"/>
</ToolTip.Content>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
</StackPanel>
<!--<Separator Width="5" Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Background="Transparent"/>-->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
place Image and Button in the same Grid. Align button to top right corner, and add margin to top and right sides of image, so the button goes outside image borders
<Grid>
<Image Margin="0,8,8,0"/>
<Button HorizontalAlignment="Right" VerticalAlignment="Top"
Width="16" Height="16" Content="x"/>
</Grid>
Here's a round button from one of my samples which looks pretty similar to what you're after.
The colours and mouseover may be different.
<SolidColorBrush x:Key="DarkLight" Color="Chocolate"/>
<SolidColorBrush x:Key="BrightMid" Color="PapayaWhip"/>
<Geometry x:Key="CloseIcon">
M19.85228,12.08996L12.093,19.849201 24.242323,31.997846 12.094,44.145998 19.852051,51.904958 32.001186,39.756277 44.150543,51.904958 51.909,44.145994 39.760246,31.997501 51.909,19.849201 44.15049,12.08996 32.001431,24.238849z M32,0C49.671021,3.1599484E-07 64,14.329407 64,31.998501 64,49.677606 49.671021,63.997003 32,63.997003 14.328003,63.997003 0,49.677606 0,31.998501 0,14.329407 14.328003,3.1599484E-07 32,0z
</Geometry>
<Style x:Key="CloseButton" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="{StaticResource BrightMid}"/>
<Setter Property="Background" Value="{StaticResource DarkLight}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
<Border CornerRadius="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"
Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"
Name="border"
BorderThickness="1"
BorderBrush="Black"
Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"
>
<Path Data="{StaticResource CloseIcon}" Stretch="Fill"
Fill="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"
/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Why can't I use AlternationCount on a Border?

In the code below if I change
<Style TargetType="{x:Type Border}">
To
<Style TargetType="{x:Type ListBoxItem}">
It will color my entire listboxitem the correct color. But I only want to hit the border background
<ListBox x:Name="FilteredMessagesListBox" BorderThickness="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" SelectionMode="Extended" Background="Transparent" AlternationCount="2">
<ListBox.Resources>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGreen"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate >
<DataTemplate>
<DockPanel Margin="0,0,0,3">
<Button x:Name="AttachmentImageButton" Click="AttachmentImageButton_Click" DockPanel.Dock="Bottom" MaxWidth="200" MaxHeight="200" HorizontalContentAlignment="Center" Visibility="{Binding ElementName=AttachmentImageButton, Converter={StaticResource cImageAttachmentToVisible}}" >
<Image Source="{Binding Path=Attachment}" x:Name="AttachmentImage" />
</Button>
<Button x:Name="AttachmentButton" Click="AttachmentButton_Click" DockPanel.Dock="Right" Visibility="{Binding ElementName=AttachmentButton, Converter={StaticResource cAttachmentToVisible}}" >
<Image Source="/MobilWPF;component/Resources/Images/PaperClip/PaperClip.jpg" Width="20" Height="20"/>
</Button>
<TextBlock Text="{Binding Converter={StaticResource cGetInstantMessageHeader}}" Width="120" TextWrapping="Wrap" HorizontalAlignment="Left" Background="Transparent" FontSize="10" DockPanel.Dock="Left"/>
<Border DockPanel.Dock="Left" HorizontalAlignment="Stretch" CornerRadius="5">
<DockPanel>
<TextBlock Margin="5,0,0,0" Text="{Binding Path=Message}" TextWrapping="Wrap" DockPanel.Dock="Left" HorizontalAlignment="Left" Background="Transparent" FontSize="12"/>
</DockPanel>
</Border>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I tried this:
<Border DockPanel.Dock="Left" HorizontalAlignment="Stretch" CornerRadius="5">
<Border.Triggers>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="0">
<Setter Property="Background" Value="LightBlue"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="1">
<Setter Property="Background" Value="LightGreen"/>
</DataTrigger>
</Border.Triggers>
<DockPanel>
<TextBlock Margin="5,0,0,0" Text="{Binding Path=Message}" TextWrapping="Wrap" DockPanel.Dock="Left" HorizontalAlignment="Left" Background="Transparent" FontSize="12"/>
</DockPanel>
</Border>
Cannot find the static member 'BackgroundProperty' on the type 'ContentPresenter'
The problem is that AlternationIndex is set on the containers (ListBoxItems in this case), not on some child within them. You could solve this by using DataTriggers that bind to AlternationIndex on the parent ListBoxItem instead:
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="0">
<Setter Property="Background" Value="LightBlue"/>
</DataTrigger>

WPF: Named Style can not be found in Resource

Exactly the below code works in a TEST project. But in my productive project It does not find the Resource, why this?
Wpf can not find this Style="{StaticResource bla}"
<TextBlock Height="23" HorizontalAlignment="Left" Margin="22,89,0,0" Text="Keywords" VerticalAlignment="Top" />
<TextBox Style="{StaticResource bla}" Height="23" HorizontalAlignment="Left" Margin="22,109,0,0" VerticalAlignment="Top" Width="244">
<Binding Path="Tags" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="False" ValidationStep="UpdatedValue" />
</Binding.ValidationRules>
</Binding>
</TextBox>
<UserControl.Resources>
<Style x:Name="bla" TargetType="TextBox">
<Setter Property="BorderBrush" Value="DarkBlue"/>
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="0,1,0,1" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<AdornedElementPlaceholder />
<Grid Margin="2,0,0,0">
<Ellipse Width="20" Height="20" Fill="Red"/>
<TextBlock Foreground="White" Text="X" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<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>
</UserControl.Resources>
In your style tag instead of name used key. you can find a resource with its key.
change this to

What's wrong with this ContentTemplate?

I'm getting an error for this content template within a style: "Must specify both Property and Value for Setter." Aren't I doing that?
<Style x:Key="LinkButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Label x:Name="ContentRoot">
<StackPanel Orientation="Horizontal">
<Viewbox Width="24" Height="24" VerticalAlignment="Center">
<Image x:Name="ButtonImage" Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=Tag}" />
</Viewbox>
<TextBlock VerticalAlignment="Center" x:Name="ButtonText" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=Content}"></TextBlock>
</StackPanel>
</Label>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonText" Property="TextBlock.TextDecorations" Value="Underline"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
And here is a button that will be using this style:
<Button Name="HelpButton" Style="{StaticResource LinkButton}" Height="30" Content="Help" Tag="Help.png"/>
Thanks!
I have loaded this up and have no such problems. The only problem I see is that your button will never have the style applied. This is because if you want the style applied you need to remove the x:Key from the style. Otherwise if you want the style applied only to the HelpButton, the definition should look like this:
<Button Name="HelpButton" Style="{StaticResource LinkButton}" Height="30" Content="Help" Tag="Help.png"/>
But I cannot see the error you are seeing.

Resources