Wpf - Template property is null in constructor - c#

After the class is initialized, template property returns the correct value but in constructor it always returns null. I tried to call ApplyTemplate() method in constructor but it didn't work.
Can anyone explain how and why that happens?
Is it possible to get template property in constructor correctly?
Thanks in advance!
Style
<Style x:Key="DesignerItemStyle" TargetType="{x:Type dataModel:Component}">
<Style.Resources>
<converter:ComponentHeightConverter x:Key="componentHeightConverter"/>
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="MinWidth" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="Height" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dataModel:Component}">
<StackPanel Orientation="Vertical" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<Grid x:Name="PART_MainGrid">
<!-- PART_ContentPresenter -->
<ContentPresenter x:Name="PART_ContentPresenter"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding ContentControl.Content}"
Margin="{TemplateBinding ContentControl.Padding}"
Cursor="Arrow"/>
<!-- PART_ResizeDecorator -->
<Control x:Name="PART_ResizeDecorator"
Visibility="Collapsed"
Template="{StaticResource ResizeDecoratorTemplate}"/>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
Template="{StaticResource MoveThumbTemplate}"
ToolTip="{Binding ToolTip}"
Cursor="SizeAll"/>
<c:RelativePositionPanel x:Name="PART_ConnectorNames"
Visibility="{Binding Path=(viewModel:ToolbarViewModel.IsPortLabelVisible),
Converter={StaticResource BooleanToVisibilityConverter}}"/>
<!-- PART_ConnectorDecorator -->
<Control x:Name="PART_ConnectorDecorator"
Visibility="Visible" Panel.ZIndex="1000"
Template="{StaticResource ConnectorDecoratorTemplate}"/>
</Grid>
<TextBlock x:Name="PART_NameBlock"
HorizontalAlignment="Center" Visibility="{Binding Path=(viewModel:ToolbarViewModel.IsComponentLabelVisible), Converter={StaticResource BooleanToVisibilityConverter}}"
TextTrimming="CharacterEllipsis" Text="{Binding DisplayedName}" Grid.Row="1">
<TextBlock.RenderTransform>
<TranslateTransform X="5" Y="5"/>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsSelected}"/>
<Condition Value="{x:Static sys:Guid.Empty}" Binding="{Binding RelativeSource={RelativeSource Self},Path=ParentID}"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="PART_ResizeDecorator" Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="PART_ConnectorDecorator" Property="Visibility" Value="Visible"/>
<Setter TargetName="PART_DragThumb" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="PART_DragThumb" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsDragConnectionOver}">
<Setter TargetName="PART_ConnectorDecorator" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Concrete Class
public Component()
{
var template = this.Template; //Here template property returns null
}

You can call UpdateDefaultStyle() method before accessing Template property.
e.g.:
var button= new Button();
button.UpdateDefaultStyle();
button.Template // template is not null here

You can override OnApplyTemplate method and access template inside this method.
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var template = Template; // template is not null here
}

Related

IntegerUpDown Control Changing Background When Textbox IsFocused

I'm creating a WPF application and am using the WPF Extended Toolkit library . I have added the IntegerUpDown control to my UserControl and when the user presses inside the textbox I want the background color to change from a dark grey to a light grey.
I have tried adding a style trigger in the xaml that triggers when the IntegerUpDown control IsFocused for the background to change. However, this did not seem to work.
<xctk:IntegerUpDown x:Name="Day" Value="{Binding DayText, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource IntegerUpDownStyle}" Minimum="{Binding MinimumDateSelection}" Maximum="{Binding MaximumDateSelection}">
<xctk:IntegerUpDown.Watermark>
<TextBlock Text="Day" Foreground="{StaticResource OffsetWhiteBrush}" Margin="0,0,60,0"/>
</xctk:IntegerUpDown.Watermark>
</xctk:IntegerUpDown>
<!-- Textbox and PasswordBox base styling for login boxes -->
<Style x:Key="IntegerUpDownStyle" TargetType="{x:Type Control}" BasedOn="{StaticResource BaseTextStyle}">
<Setter Property="MaxWidth" Value="400" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="{StaticResource FontSize20}" />
<Setter Property="FontFamily" Value="{StaticResource LatoRegular}" />
<Setter Property="Background" Value="{StaticResource DarkGreyBrush}" />
<Setter Property="Margin" Value="0,20,0,0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="{StaticResource LightGreyBrush}" />
</Trigger>
<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>
With the styling I've added I expected the background of the control to change from a dark grey to a light grey but nothing happened. How can I make this happen?
I tried this problem in my own app,and it's finished.Here's code:
<Window
x:Class="WpfApp16.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:local="clr-namespace:WpfApp16"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<Style x:Key="IntegerUpDownStyle" TargetType="xctk:IntegerUpDown">
<Style.Triggers>
<EventTrigger RoutedEvent="ValueChanged">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Background.Color"
From="DarkGray"
To="Transparent"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<xctk:IntegerUpDown Width="200" Style="{StaticResource IntegerUpDownStyle}">
<xctk:IntegerUpDown.Background>
<SolidColorBrush Color="Transparent" />
</xctk:IntegerUpDown.Background>
</xctk:IntegerUpDown>
</StackPanel>
For more Information ,look this linke:WPF Animation dependency issue
The same trigger in IntegerUpDown source code, so the outside trigger was no longer effective.
IntegerUpDown source code:
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="PART_TextBox"
Property="FocusManager.FocusedElement"
Value="{Binding ElementName=PART_TextBox}" />
</Trigger>
I tried using GotFocus and LostFocus events.
xaml:
<xctk:IntegerUpDown x:Name="Day"
LostFocus="IntegerUpDown_LostFocus"
GotFocus="IntegerUpDown_GotFocus"
Focusable="True"
Value="{Binding DayText, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource IntegerUpDownStyle}" Minimum="{Binding MinimumDateSelection}" Maximum="{Binding MaximumDateSelection}">
<xctk:IntegerUpDown.Watermark>
<TextBlock Text="Day" Foreground="{StaticResource OffsetWhiteBrush}" Margin="0,0,60,0"/>
</xctk:IntegerUpDown.Watermark>
</xctk:IntegerUpDown>
cs code:
private void IntegerUpDown_GotFocus(object sender, RoutedEventArgs e)
{
Day.Background = new SolidColorBrush(Colors.Gray);
}
private void IntegerUpDown_LostFocus(object sender, RoutedEventArgs e)
{
Day.Background = new SolidColorBrush(Colors.DarkGray);
}
After seeing the answer from #J.B.D I edited the ControlTemplate for the IntegerUpDown control to change the back
<ControlTemplate x:Key="ControlControlTemplate1" TargetType="{x:Type Control}">
<xctk:ButtonSpinner x:Name="PART_Spinner" AllowSpin="{Binding AllowSpin, RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ButtonSpinnerLocation="{Binding ButtonSpinnerLocation, RelativeSource={RelativeSource TemplatedParent}}" Background="{TemplateBinding Background}" HorizontalContentAlignment="Stretch" IsTabStop="False" ShowButtonSpinner="{Binding ShowButtonSpinner, RelativeSource={RelativeSource TemplatedParent}}" VerticalContentAlignment="Stretch">
<xctk:WatermarkTextBox x:Name="PART_TextBox" AutoMoveFocus="{Binding AutoMoveFocus, RelativeSource={RelativeSource TemplatedParent}}" AutoSelectBehavior="{Binding AutoSelectBehavior, RelativeSource={RelativeSource TemplatedParent}}" AcceptsReturn="False" BorderThickness="0" ContextMenu="{TemplateBinding ContextMenu}" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="True" IsUndoEnabled="True" MinWidth="20" MaxLength="{Binding MaxLength, RelativeSource={RelativeSource TemplatedParent}}" Padding="{TemplateBinding Padding}" TextAlignment="{Binding TextAlignment, RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="NoWrap" TabIndex="{TemplateBinding TabIndex}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" WatermarkTemplate="{Binding WatermarkTemplate, RelativeSource={RelativeSource TemplatedParent}}" Watermark="{Binding Watermark, RelativeSource={RelativeSource TemplatedParent}}">
<xctk:WatermarkTextBox.Style>
<Style TargetType="{x:Type xctk:WatermarkTextBox}">
<Setter Property="Background" Value="{StaticResource DarkGreyBrush}" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="{StaticResource LightGreyBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</xctk:WatermarkTextBox.Style>
</xctk:WatermarkTextBox>
</xctk:ButtonSpinner>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {ComponentResourceKey ResourceId=ControlMouseOverBorderKey, TypeInTargetAssembly={x:Type Themes:ResourceKeys}}}"/>
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="False"/>
<Condition Binding="{Binding AllowTextInput, RelativeSource={RelativeSource Self}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsReadOnly" TargetName="PART_TextBox" Value="True"/>
</MultiDataTrigger>
<DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="IsReadOnly" TargetName="PART_TextBox" Value="True"/>
</DataTrigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {ComponentResourceKey ResourceId=ControlSelectedBorderKey, TypeInTargetAssembly={x:Type Themes:ResourceKeys}}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="FocusManager.FocusedElement" TargetName="PART_TextBox" Value="{Binding ElementName=PART_TextBox}"/>
<Setter TargetName="PART_TextBox" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Please look at the start of the control template and the WatermarkTextBox. The WatermarkTextBox.Style is what I added to make the background change when the textbox is focused.
To override the COntrolTemplate, right click on the IntegerUpDown Control and then press Edit Template

Custom Control Background Color in WPF

I have created a custom control as you see below (Generic.xaml):
<Style TargetType="{x:Type local:MyCC}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCC}">
<Grid Name="grd" Height="{Binding Height}" Width="{Binding Width}">
<Rectangle Name="FirstRec" Fill="Blue"/>
<Rectangle Name="SecondRec" Fill="Black" Margin="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property = "IsMouseOver" Value = "True">
<Setter Property = "Background" Value = "Red" />
</Trigger>
</Style.Triggers>
</Style>
For FirstRec I want to get the Foreground color of the CC (instead of blue) and for the SecondRec I need to get the Background (instead of black). Therefore now the trigger does not work properly! I also don't want to bind the Height and Width of the Grid because the CC has its own height and width but I don't know how to use it! Would you please help me?!
EDIT:
It is actually a switch that has a status. if status == 0 it shows an empty rectangle. if status == 1 it shows a filled rectangle. if status == 3 || status == 4 it shows a red cross on it. here is the cc:
<Style TargetType="{x:Type local:BreakerCC}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BreakerCC}">
<Grid Name="grd" Background="{TemplateBinding Background}" >
<Rectangle Name="MainRectangle" StrokeThickness="1" Stroke="{TemplateBinding Foreground}"/>
<Path Name="Line1" Stroke="Red" StrokeThickness="1" Stretch="Fill">
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="1,1" />
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0x00">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x01">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x02">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x03">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
<Path Name="Line2" Stroke="Red" StrokeThickness="1" Stretch="Fill">
<Path.Data>
<LineGeometry StartPoint="0,1" EndPoint="1,0" />
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0x00">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x01">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x02">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x03">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And this is the definition in MainWindow.xaml
<Window.Resources>
<Style x:Key="230KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="132KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style x:Key="400KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Purple"/>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<CC:BreakerCC Status="{Binding Status}" Style="{StaticResource 132KV}" Height="20" Width="20"/>
</StackPanel>
</Grid>
But when the status is 3 or 4 i need to change the Foreground to Red and that doesn't work!
Use TemplateBindings for the Brushes. Binding Width and Height is not at all necessary.
<Style TargetType="local:MyCC">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyCC">
<Grid>
<Rectangle Fill="{TemplateBinding Foreground}"/>
<Rectangle Fill="{TemplateBinding Background}" Margin="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
As a note, instead of a Grid you would usually have a Border element and assign TemplateBindings to its Background, BorderBrush and BorderThickness properties - as done by default by Visual Studio when you create a new custom control.
EDIT: It seems that you do not need a custom control at all. Just create ContentControl styles like these:
<Window.Resources>
<Style TargetType="ContentControl" x:Key="BaseStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Path x:Name="path" Stroke="{TemplateBinding Foreground}"
Data="{TemplateBinding Content}" Stretch="Fill"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0">
<Setter TargetName="path"
Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="1">
<Setter TargetName="path"
Property="Visibility" Value="Hidden"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Black"/>
<Setter Property="BorderBrush" Value="{Binding Foreground,
RelativeSource={RelativeSource Self}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
</Style>
<Style x:Key="230KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="132KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style x:Key="400KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Purple"/>
</Style>
</Window.Resources>
<StackPanel>
<ContentControl Style="{StaticResource 230KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
<ContentControl Style="{StaticResource 132KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
<ContentControl Style="{StaticResource 400KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
</StackPanel>

Enable ListboxItem on Mouseclick and Selection

I have a Listbox with Image, TextBox, TextBlock bound to a ObservableCollection.
What I want to achieve is that those ListboxItems can be edited by the user just like Windows Explorer Style.
Select ListboxItem - MouseClick once - ENABLE Textbox. I got a MultiDatatrigger that works for the isEnabled Property. But I don't want it to trigger on the first click on the items. User first needs to select one and then click again.
<ListBox x:Name="Listbox1" Margin="0,12,0,5" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="ListBoxImage" Source="{Binding FileIcon}" Height="30" Width="30"/>
<StackPanel VerticalAlignment="Center" Orientation="Vertical" Width="150">
<TextBox BorderThickness="0" FontSize="11" IsEnabled="False" x:Name="ListBoxFileName" TextWrapping="Wrap" Text="{Binding FileName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="7,0,0,0">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
<ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" />
<Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" />
<Setter TargetName="PART_ContentHost" Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" />
<Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" />
<Setter TargetName="PART_ContentHost" Property="Background" Value="White"/>
<Setter Property="Height" Value="25"></Setter>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Value="False" Property="IsEnabled" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
<StackPanel VerticalAlignment="Center" Orientation="Vertical" Width="70">
<TextBlock x:Name="ListBoxFileCreation" FontSize="11" TextWrapping="Wrap" Text="{Binding FileCreation, StringFormat='dd.MM.yyyy'}" Margin="10,0,5,0" />
</StackPanel>
</StackPanel>
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsClicked}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="ListBoxFileName" Property="IsEnabled" Value="true"/>
</MultiDataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="3,5,3,5"/>
<!--<EventSetter Event="MouseDown" Handler="ListBoxItem_MouseDown"/>-->
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
This is what I have so far. Thank you in advance.

WPF Edit Resource Dictionary dynamically passing parameters

I have a style defined in my resource dictionary so the style can be used in all over my application.
<Style x:Key="HyperlinkStyle" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource Color3}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource Color3Pressed}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource Color2NotEnabled}" />
</Trigger>
</Style.Triggers>
</Style>
I use the style in Datagrid like this :
<DataGridTemplateColumn Width="140*" CanUserReorder="False" CanUserResize="True" Header="">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate />
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource DatagridCellHyperlinkStyle}">
<Setter Property="IsEnabled" Value="{Binding Path=MyObject, Converter={StaticResource ConverterMyObject}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}" VerticalAlignment="Center">
<TextBlock Width="Auto" Height="Auto" TextTrimming="CharacterEllipsis">
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<InlineUIContainer TextDecorations="{Binding Path=TextDecorations, RelativeSource={RelativeSource AncestorType=TextBlock}}" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=TextBlock}}">
<ContentPresenter Width="Auto" Height="Auto" Content="{Binding DataContext.MyObject.Name, RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
</InlineUIContainer>
<Hyperlink.Style>
<Style TargetType="Hyperlink" BasedOn="{StaticResource HyperlinkStyle}">
<EventSetter Event="Hyperlink.Click" Handler="Clic" />
</Style>
</Hyperlink.Style>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
This works great but I would like to be able to have 2 colors in my style depending on a parameter.
For example, my datagrid has 1500 rows, I want to highlight 100 rows from the collection by changing their hyperlink color.
So I thought the best was to set the Tag property of the hyperlink to a custom value and use it in the style. Following this answer : https://social.msdn.microsoft.com/Forums/vstudio/en-US/d3424267-ed1f-4b30-90a1-5cca9843bd22/problem-making-a-trigger-on-the-tag-property?forum=wpf, I made the changes below :
xmlns:sys="clr-namespace:System;assembly=mscorlib"
First I've set the tag manually for each row to see if the style changes :
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
and added this trigger to my hyperlink's style:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte> <!-- My highlighted object -->
</Trigger.Value>
<Setter Property="Foreground" Value="{StaticResource Color1}" />
</Trigger>
But it doesn't work when I launch my application (I still have "Color3" whereas I want "Color1" when Tag is equals to 10.
I've checked the output there isn't any error.
I've tried to change "sys:Byte" by "sys:String" but the result was the same.
Do I need to change my approach for this problem ? I've read maybe we can't add trigger on Tag Property.
Thank you
I suggest if you set the tag like this
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
Then write the trigger in the same way:
<Trigger Property="Tag" Value="10">
...setter
</Trigger>
Or if in hyperlink you use Byte type as Tag:
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<Hyperlink.Tag>
<sys:Byte>10</sys:Byte>
</Hyperlink.Tag>
</Hyperlink>
Then same goes in the trigger:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte>
</Trigger.Value>
...setter
</Trigger>

Text Trimming on DataGrid Template Column

I have the following Column in my datagrid :
<DataGridTemplateColumn CanUserReorder="False" CanUserResize="True" Header="">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate />
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource DatagridCellHyperlinkStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}" VerticalAlignment="Center">
<TextBlock Width="Auto" Height="Auto" TextTrimming="CharacterEllipsis">
<Hyperlink>
<InlineUIContainer TextDecorations="{Binding Path=TextDecorations, RelativeSource={RelativeSource AncestorType=TextBlock}}" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=TextBlock}}">
<ContentPresenter Width="Auto" Height="Auto" Content="{Binding DataContext.Value, RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
</InlineUIContainer>
<Hyperlink.Style>
<Style TargetType="Hyperlink" BasedOn="{StaticResource HyperlinkStyle}">
<EventSetter Event="Hyperlink.Click" Handler="Click" />
</Style>
</Hyperlink.Style>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
The hyperlink works perfectly (with my style also) but the text trimming doesn't work. How can I change my code to make it work ?
The 2 styles attached :
<Style x:Key="DatagridCellHyperlinkStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Padding" Value="5" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="FontSize" Value="14" />
<Setter Property="FontFamily" Value="Helvetica" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="{StaticResource CouleurBouton}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurBouton}"/>
<Setter Property="Foreground" Value="{StaticResource ResourceKey=CouleurFond}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurBouton}"/>
<Setter Property="Foreground" Value="{StaticResource ResourceKey=CouleurFond}" />
</Trigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurBoutonHover}"/>
<Setter Property="Foreground" Value="{StaticResource ResourceKey=CouleurTexteBoutonHover}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="HyperlinkStyle" TargetType="{x:Type Hyperlink}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource CouleurBoutonPressed}" />
</Trigger>
</Style.Triggers>
<Setter Property="Foreground" Value="{DynamicResource CouleurBouton}" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
</Style>
Thank you !
You have nothing that will restrict the TextBlock.Width, so the text in it will never wrap, or be trimmed. To fix this problem, you just need to set some kind of Width restriction on it... you could try something like this:
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}" VerticalAlignment="Center">
<TextBlock MaxWidth="250" TextTrimming="CharacterEllipsis">
...
Well, for WPF engine to understand that the trimming is needed it should see that the control cannot be put into the space available. If the control can be resized(AutoSize) it will just increase its dimensions without any trimming.
From MSDN:
Gets or sets the text trimming behavior to employ when content
overflows the content area.
And I can't see anything in your template that suggests that the space limit will be encountered.
So try to set width limit, either on Column, or on the TextBlock. Or restrict the resize in some other way.
<TextBlock Width="Auto" Height="Auto"
MaxWidth="100"
MinWidth="30"
TextTrimming="CharacterEllipsis">

Categories

Resources