I am doing validation of all text boxes using IDataErrorInfo on my WPF form like this:
<TextBox Name="txtAddress"
Validation.Error="Validation_Error"
Text="{Binding Path=Address, UpdateSourceTrigger=LostFocus,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}">
// If I have many TextBoxes to validate, I have to copy this and paste
// for each TextBox in XAML. This obviously violates DRY. How do I define
// this at one place and use it for all TextBoxes on my form?
<Validation.ErrorTemplate>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="16" Height="16" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!"
VerticalAlignment="center" HorizontalAlignment="center"
FontWeight="Bold" Foreground="white"/>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
This is my Validation_Error method used above:
private void Validation_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
mNumErrors++;
}
else
{
mNumErrors--;
}
}
If I have many Textboxes on my form, I have to copy the section above into each TextBox definition in XAML. How do I define it on one place and use it for all TextBoxes?
Thanks,
1 Way. You can move ControlTemplate to the Resources of application or window. And add into textBoxes StaticResource like this.
ControlTemplate in Resources with x:Key property.
<ControlTemplate x:Key="MyErrorTemplate">
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="16" Height="16" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center"
FontWeight="Bold" Foreground="white"/>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="5" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
TextBox with assigned ErrorTemplate.
<TextBox Validation.ErrorTemplate="{StaticResource MyErrorTemplate}" />
2 Way. If all TextBoxes should contain this ErrorTemplate you can define TextBox Style in the resources and add ErrorTemplate into it. The Style will be applied to all TextBoxes.
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Related
I am trying to add filtering to my WPF app, so I figured that I want to have an ellipse, and inside it will be a TextBox whose Text will be bound to a FilterText property in my ViewModel.
What I have tried:
<TextBox
Width="30"
Height="30">
<TextBox.Template>
<ControlTemplate>
<Grid>
<Ellipse Stroke="Black" StrokeThickness="1" />
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding FilterText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextElement.Foreground="Black" />
</Grid>
</ControlTemplate>
</TextBox.Template>
</TextBox>
I took this from the same example, but with Label.
This displays the ellipse, but no TextBox inside it.
How can I create an ellipse WITH a TextBox?
Try this
<Grid>
<Ellipse Stroke="Black" StrokeThickness="1"/>
<TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
Fixed it by wrapping the TextBox inside a Border and setting the Border's CornerRadius:
<Border
Width="30"
Height="30"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="30">
<TextBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="Transparent" //important to lose the TextBox look
BorderBrush="Transparent" //important to lose the TextBox look
BorderThickness="0" //important to lose the TextBox look
Text="{Binding FilterText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Border>
I wish to display a ToolTip for an entry in a Listbox.
The Toolkit will contain a Textbox and a copy (larger) of the Image in the entry in the Listbox
I can get either the Text in the Textbox Or the Image to display.
The code which displays the image but not the text is
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="#EEFFFFFF" BorderBrush="#FFCCCCCC"
HorizontalAlignment="Center" VerticalAlignment="Center"
BorderThickness="1">
<Grid>
<StackPanel Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<Image x:Name="img" ToolTipService.Placement="Top"
Source="{Binding Path=ImageUri}" Height="64" Stretch="Uniform" Width="64">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" x:Name="scaleTrans"/>
</TransformGroup>
</Image.RenderTransform>
<Image.ToolTip>
<ToolTip BorderBrush="{x:Null}" Background="{x:Null}" Effect="{x:Null}"
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}"
HasDropShadow="False">
<Border Background="{x:Null}" VerticalAlignment="Center" Margin="0" Width="600"
HorizontalAlignment="Center">
<Grid Background="{x:Null}">
<StackPanel >
<TextBlock Margin="5" Padding="5" FontSize="14" FontWeight="Bold"
Text="{Binding Path=FTitle}"
Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
<Border Margin="8,0,8,12.5" VerticalAlignment="top">
<Image Source="{Binding Path=Source}"/>
</Border>
</StackPanel>
</Grid>
</Border>
</ToolTip>
</Image.ToolTip>
</Image>
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
This code is part of the code for which is used by a ListBox
The code below (as in the list above display the Image in the tooltip but not the Textbox
<ToolTip BorderBrush="{x:Null}" Background="{x:Null}" Effect="{x:Null}"
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}"
HasDropShadow="False">
<Border Background="{x:Null}" VerticalAlignment="Center"Margin="0" Width="600"
HorizontalAlignment="Center">
<Grid Background="{x:Null}">
<StackPanel >
<TextBlock Margin="5" Padding="5" FontSize="14" FontWeight="Bold"
Text="{Binding Path=FTitle}"
Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
<Border Margin="8,0,8,12.5" VerticalAlignment="top">
<Image Source="{Binding Path=Source}"/>
</Border>
</StackPanel>
</Grid>
</Border>
</ToolTip>
If you remove
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}" from <ToolTip
The Text works as expected but the Image now fails (as expected)
I have tried to
a) modify the original so the TextBlock binding point to the FTitle entry observable Collection driving the listbox entries
<TextBlock Margin="5" Padding="5" FontSize="14" FontWeight="Bold"
Text="{Binding Path=DataContext.FTitle, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
b) moved the datacontext in to Image
<Border Margin="8,0,8,12.5" VerticalAlignment="top">
<Image Source="{Binding Path=DataContext.Source, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Image}}}"/>
</Border>enter code here
Neither worked. (I did try many variations But none worked.
I would be grateful for either solution
{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}} will bind the UIElement (a ListBoxItem) as the DataContext for the tooltip. It seems you want the DataContext of the ListBoxItem in order to bind to properties of the underlying model. In which case, try changing your DataContext binding to be: {Binding Path=PlacementTarget.DataContext, RelativeSource={x:Static RelativeSource.Self}}
I have a dynamically generated DataGrid bound to a DataTable property in my ViewModel.
I have AutoGenerateColumnHeaders = true, and it's working fine. However, I'm using a DataTemplate to cover the Header with a StackPanel containing a Label and Button. I cannot seem to figure out how to bind the Label Content to the DataGridColumnHeader. I have tried with and without FindAncestor, but I believe the following is the closest to where I need to be...Question is on the Label Content="{}"
<local:UserControlViewBase.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Width="Auto" Orientation="Horizontal">
<Label Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:UserControlViewBase}},Path=DataContext.TestList.ColumnName}" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:UserControlViewBase.Resources>
//local:UserControlViewBase is just a UserControl with some extra bells and whistles added.
I'm fairly new to WPF and I'm assuming I'm just missing something with the binding - I'm still learning.
Thanks.
This is what I did to get it to work. I had to change the findancestor to look for the DataGridColumnHeader instead of the user control. I then was able to access the Column.Header property:
<local:UserControlViewBase.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Width="Auto" Orientation="Horizontal">
<Label Width="75" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridColumnHeader}},Path=Column.Header}" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:UserControlViewBase.Resources>
I am trying to create a Custom tooltip Control. This control is inherited from ToolTip class. My Custom Tooltip will have a header and a content area. Content could be normal text or any other content (Image, richtextbox etc). Following is the Template Style that custom tooltip control.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type customControls:FlyoutHelp}">
<Border BorderThickness="0" Margin="15" Width="300">
<Border.Effect>
<DropShadowEffect Opacity="0.7" />
</Border.Effect>
<StackPanel TextBlock.FontFamily="Trebuchet MS" TextBlock.FontSize='12'>
<TextBlock Background="{StaticResource DellBlue}" Height="23" Foreground="#FFFFFF" Padding="0,4,0,0" TextAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border Background="{StaticResource DellLightGrey}" TextBlock.Foreground="{StaticResource DarkestGrey}" Padding="8">
<ContentControl Content="{Binding HelpContent, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</Border>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Now as you can see in my template that I am using ContentControl for showing the content of the tooltip. The problem is when my HelpContent is just plain String, it doesn't wrap that text. I can't replace ContentControl with TextBlock because HelpContent could be some other type too (image, richtextbox etc). Can anyone please provide me what is the best way to fix this problem? I will be really very thankful.
Replace ContentControl tag with:
<ContentPresenter Content="{TemplateBinding HelpContent}">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
[Note: you can leave it as a ContentControl, but ContentPresenter is lighter and follows conventions]
Change StackPanel to Grid since it doesn't know the width for it to wrap.
<Grid TextBlock.FontFamily="Trebuchet MS" TextBlock.FontSize='12'>
<Grid.RowDefinitions>
<RowDefinitions/>
<RowDefinitions/>
<Grid.RowDefinitions/>
<TextBlock Grid.Row="0" Background="{StaticResource DellBlue}" Height="23" Foreground="#FFFFFF" Padding="0,4,0,0" TextAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border Grid.Row="1" Background="{StaticResource DellLightGrey}" TextBlock.Foreground="{StaticResource DarkestGrey}" Padding="8">
<ContentControl Content="{Binding HelpContent, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</Border>
</Grid>
I'm using LongListSelector with JumpListStyle, when I click on group header it opens list with headers (image + text), but last images aren't loading. Here is a image:
So how can I make LongListSelector to load all images ?
I'm currently having the same problem ...
My JumpListStyle is an image.
The JumpList is in "List" mode, like you.
If I click on a header in the LongListSelector (with about 100 items) without scrolling all the list, the JumpList (containing 6 groups) is loading but with some images missing.
If I click on an JumpList item without image, and come back on the JumpList, the missing image is now loaded.
If I scroll all the LongListSelector items, the JumpList is ok now (all the images of the JumpList are loaded).
<Style x:Key="LongListSelectorJumpListStyle" TargetType="phone:LongListSelector">
<Setter Property="GridCellSize" Value="111,111"/>
<Setter Property="LayoutMode" Value="List" />
<Setter Property="Margin" Value="18,12,0,0"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{StaticResource SVodBackgroundBrush}" BorderBrush="Gray" BorderThickness="2"
Height="62" Width="286" Margin="20,20,20,20"
HorizontalAlignment="Left"
Visibility="{Binding EmptyGroup, Converter={StaticResource VisibilityInverseConverter}}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Key}" Visibility="{Binding Key, Converter={StaticResource ratingAvailableConverter}}" FontSize="30" Foreground="DarkGray" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Source="{Binding Key, Converter={StaticResource allRatingsConverter}}"/>
<Grid Visibility="{Binding Key, Converter={StaticResource ratingUnavailableConverter}}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto">
<TextBlock Text="?" FontSize="40" Foreground="DarkGray" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto"/>
</Grid>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>