XAML Binding Parent field to a Child value from ResourceDictionnary - c#

I made a style to create a TextBox with a Placeholder.
<Style TargetType="TextBox" x:Key="PlaceholderTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<Grid>
<TextBox VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
x:Name="MessageBox"
Background="Transparent"
TextWrapping="Wrap"
BorderThickness="0"
Margin="2,0,0,0"
Text="{Binding Message, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<TextBlock IsHitTestVisible="False"
Text="{TemplateBinding Tag}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="4,0,0,0"
Foreground="Gray"
FontStyle="Italic">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Text,
ElementName=MessageBox}" Value="">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It works well, but when I want to access the data from my TextBox, I can't get it to retrieve the data.
<StackPanel Orientation="Horizontal">
<Label Content="Filtre : " />
<TextBox x:Name="TxtFiltre" Width="120" Height="16" Margin="4,0,4,0"
KeyUp="TxtFiltre_KeyUp" Style="{StaticResource PlaceholderTextBox}"
Tag="Search" />
</StackPanel>
I tried to bind the Text value from the TextBox and the TextBlock in style, but none worked.
In debug I saw that the value entered in my TextBox can be found on the Text element, but the source is ParentTemplate and not Default. I don't understand the difference and if it has something to do with the style and not being able to retrieve the data.

If you want to re template the textbox then you need to start with a viable textbox template.
I wasn't particularly careful with what follows so consider this an illustration rather than bullet proof cut and paste.
It uses the background brush for the watermark.
<Window.Resources>
<Style TargetType="{x:Type TextBox}" x:Key="WatermarkTextBoxStyle">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation"
Value="None" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="MinWidth"
Value="120" />
<Setter Property="MinHeight"
Value="20" />
<Setter Property="AllowDrop"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border"
CornerRadius="2"
Padding="2"
BorderThickness="1">
<Border.Background>
<VisualBrush Stretch="None"
AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock FontSize="12"
Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}"
Foreground="LightGray" >
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Opacity" Value="1"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="True">
<Setter Property="Opacity" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Style="{StaticResource WatermarkTextBoxStyle}"
Tag="Watermark Text"/>
A markup in place version might be clearer. There's not a huge amount to this. I set the opacity to zero if the textbox has focus ( so the user is about to start typing ) or the text is not "". Meaning they typed something in.
<TextBox>
<TextBox.Background>
<VisualBrush Stretch="None"
AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock FontSize="12"
Text="Watermark Text"
Foreground="LightGray" >
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Opacity" Value="1"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="True">
<Setter Property="Opacity" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>

Related

Bind Textbox Text with style from template to a viewmodel

I have some textbox whith style from a template like this
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<TextBox Background="White"
FontFamily="Poppins" FontSize="11"
VerticalAlignment="Center"
Padding="5"
Name="SearchBox"
Foreground="Black"
Margin="2"
BorderThickness="0"
Text="{TemplateBinding Text}"
/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just to show an placeholder. This works but something goes wrong when I try to bind property Text to a view model.
<TextBox Text="{Binding NombreCliente}"
Style="{StaticResource SearchTextBox}"
Grid.Row="1"
Tag="Nombre"/>
I've done test and while the textbox have this style the binding always return null or "".
I find in other ask that there's something whith binding parent and they solve whith this
<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text,
UpdateSourceTrigger=PropertyChanged}"....
But if i bind text to a template parent, how do I bind to viewmodel?
A template of a TextBox should not contain another TextBox control.
Replace it with a ScrollViewer and set the FontFamily and FontSize properties using Style setters:
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" Margin="2" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
If this is a template for use in a TextBox, then you have created it incorrectly.
In fact, instead of giving the TextBox room to display the text, you have overlapped it on top with another TextBox that has nothing to do with the one this template will use.
TextBox to display text looks in its template for a ScrollViewer named PART_ContentHost.
And all the property settings of the TextBox must be moved to Setters outside the template.
Example template:
<Style TargetType="TextBox">
<Setter Property="Background" Value="White"/>
<Setter Property="FontFamily" Value="Poppins"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
CornerRadius="8" x:Name="container"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"/>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF TextBox MaxLength Property does not work after applying some style

I have an issue in my C# code. Could you please help me? I have a textbox with such XAML code:
<TextBox
Margin="0,10"
x:Name="SomeName"
TextAlignment="Center"
FontWeight="Bold"
Focusable="True"
MaxLength="100"
Width="200"
Style="{StaticResource SomeStyle}"
Text="{Binding PropName, UpdateSourceTrigger=PropertyChanged}" />
UPDATE
Here is my SomeStyle code:
<Style x:Key="SomeStyle" TargetType="{x:Type TextBox}" >
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}" >
<Grid ClipToBounds="True" >
<TextBox Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Panel.ZIndex="2" />
<TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="BorderBrush" Value="Transparent" />-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I remove a Style prop, the MaxLength prop work properly. This referenced style does not contain a constraint for MaxLength. Any ideas?
You have others TextBoxes in your TextBox Control Template and you don't pass them MaxLength value, so it doesn't work. What you are trying to do with this template?

Stop combobox from closing

I am using custom control, MultiSelectComboBox that is already placed on code project (https://www.codeproject.com/Articles/563862/Multi-Select-ComboBox-in-WPF). This combobox has checkboxes inside of it. I am trying to achieve following:
When combobox opens, I want to close it by clicking only on Ok/Cancel button. Cancel will close it and none of the checkboxes will be checked. I don't want it to close when I click with my mouse on a window or anywhere else besides Ok/Cancel button.
Here is the part of the code:
<ComboBox x:Name="cmbMultiSelect" Style="{StaticResource MultiSelectComboBoxStyler}">
<ComboBox.ToolTip >
<ToolTip DataContext="{Binding Path=PlacementTarget.Parent, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock TextWrapping="Wrap" Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource CommmaToNewLineConverter}}"/>
</ToolTip>
</ComboBox.ToolTip>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="cbSelector"
Content="{Binding Title, UpdateSourceTrigger=PropertyChanged}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"
Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"
Click="cbSelector_OnClick"/>
</DataTemplate>
</ComboBox.ItemTemplate>
Now, here it my style, MultiSelectComboBoxStyler:
<Style x:Key="MultiSelectComboBoxStyler" TargetType="{x:Type ComboBox}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="True"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox/>
<!-- Do not really need to specify in this instance, since the ItemTemplate is going to be overwritten -->
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton Name="ToggleButton"
Grid.Row="0"
Grid.Column="0"
Content="{Binding Path=Text, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"
Focusable="false"
ClickMode="Press"
HorizontalContentAlignment="Left">
<ToggleButton.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="18"/>
</Grid.ColumnDefinitions>
<Border x:Name="Border"
Grid.ColumnSpan="2"
CornerRadius="2"
Background="White"
BorderBrush="{StaticResource NormalBorderBrush}"
BorderThickness="1,1,1,1" />
<Border x:Name="BorderComp"
Grid.Column="0"
CornerRadius="2"
Margin="1"
Background="White"
BorderBrush="{StaticResource NormalBorderBrush}"
BorderThickness="0,0,0,0" >
<TextBlock x:Name="txtOnToggleButton"
Background="White"
Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
TextTrimming="WordEllipsis"
TextWrapping="Wrap"
Padding="3" />
</Border>
<Path x:Name="Arrow"
Grid.Column="1"
Fill="{StaticResource GlyphBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource MouseHoverBrush}" />
<Setter TargetName="txtOnToggleButton" Property="Background" Value="{StaticResource MouseHoverBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
<Popup Name="Popup"
Placement="Bottom"
AllowsTransparency="True"
Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
<theme:SystemDropShadowChrome Name="Shdw"
Color="Transparent"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
BorderThickness="1"
BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<ScrollViewer Name="DropDownScrollViewer" Margin="4,0,4,30" SnapsToDevicePixels="True">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Height="0" Width="0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Name="OpaqueRect"
Height="{Binding ElementName=DropDownBorder,Path=ActualHeight}"
Width="{Binding ElementName=DropDownBorder,Path=ActualWidth}"
Fill="{Binding ElementName=DropDownBorder,Path=Background}" />
</Canvas>
<ItemsPresenter Name="ItemsPresenter"
KeyboardNavigation.DirectionalNavigation="Contained"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ScrollViewer>
<StackPanel Orientation="Horizontal">
<Button Name="btnOk" Content="Ok" VerticalAlignment="Bottom" Margin="2, 0, 2, 2"
Width="50" Height="25"
Background="{StaticResource WindowBackgroundBrush}"
Command="{Binding OkCommand}">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowFilterButtons,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:MultiSelectComboBox}}}"
Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Name="btnCancel" Content="Cancel" VerticalAlignment="Bottom" Margin="2, 0, 2, 2"
Width="50" Height="25"
Background="{StaticResource WindowBackgroundBrush}"
Command="{Binding CancelCommand}">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowFilterButtons,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:MultiSelectComboBox}}}"
Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</Border>
</theme:SystemDropShadowChrome>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.HasDropShadow" Value="true">
<Setter TargetName="Shdw" Property="Margin" Value="0,0,5,5"/>
<Setter TargetName="Shdw" Property="Color" Value="#71000000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
This is how I use custom control in my view:
<controls:MultiSelectComboBox Width="200" Height="30" HorizontalAlignment="Left" DefaultText="All" ItemsSource="{Binding Chains}" SelectedItems="{Binding SelectedChains, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ShowFilterButtons="True"/>
Although I am pretty new to WPF I was able to understand some things but again this issue is giving me headaches. I am stuck. I know that there is something to do with toggle button but no success in resolve it. I appreciate all the help I can get.
Since you are using multiselectbox control, you should add new dependencyproperty
Also, Popup tag should look like this
IsOpen="{Binding Path=IsChecked, ElementName=ToggleButton}"
While ToggleButton should look like:
IsChecked="{Binding Path=ControlComboBox, Mode=TwoWay,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl},
UpdateSourceTrigger=PropertyChanged}"
Command="{Binding PressedCommand}"
And at the end you should use MultiSelectCombBox in this way:
ControlComboBox="{Binding ManageComboBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Difference between Typed Style and setting ItemContainerStyle

I have a Style for my TreeViewItems which at the moment is applied to all because he has no Key.
<Style TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid x:Name="gChildren">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle x:Name="HorLin" Grid.Row="0" Height="1" Stroke="Black" SnapsToDevicePixels="True" VerticalAlignment="Bottom" />
<Rectangle x:Name="VerLinUp" Grid.Row="1" Width="1" Height="20" Stroke="Black" SnapsToDevicePixels="True" />
<Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="3" Padding="6" Grid.Row="2" Margin="2,0">
<ContentPresenter Name="PART_Header" ContentSource="Header" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Rectangle x:Name="VerLinDown" Grid.Row="3" Width="1" Height="10" Stroke="Black" SnapsToDevicePixels="True" />
<ItemsPresenter x:Name="itemPresenter" Grid.Row="4" HorizontalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count, Converter={StaticResource IsGreaterThanConv}, ConverterParameter=0}" Value="false">
<Setter TargetName="VerLinDown" Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource HasParentMoreChildren}}" Value="false">
<Setter TargetName="HorLin" Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsParentTreeViewItem}}" Value="false">
<Setter TargetName="VerLinUp" Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsParentTreeViewItem}}" Value="true">
<Setter TargetName="VerLinUp" Property="Height" Value="10" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsFirstOrLastItem}}" Value="2">
<Setter TargetName="HorLin" Property="Width" Value="{Binding ElementName=gChildren, Path=ActualWidth, Converter={StaticResource ArithmeticConverter}, ConverterParameter=/2}" />
<Setter TargetName="HorLin" Property="HorizontalAlignment" Value="Right" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsFirstOrLastItem}}" Value="1">
<Setter TargetName="HorLin" Property="Width" Value="{Binding ElementName=gChildren, Path=ActualWidth, Converter={StaticResource ArithmeticConverter}, ConverterParameter=/2}" />
<Setter TargetName="HorLin" Property="HorizontalAlignment" Value="Left" />
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Panel.Background" Value="{StaticResource SelectedItemAreaBrush}" />
<Setter TargetName="Bd" Property="Border.BorderBrush" Value="{StaticResource SelectedItemBorderBrush}" />
<Setter TargetName="Bd" Property="TextElement.Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="spChildren" HorizontalAlignment="Center" IsItemsHost="True" Margin="4,0,4,6" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
When I leave it like that everything works like I want it too. But if I give my Style a Name and set the ItemContainerStyle on my TreeView it looks different
<Style x:Key="GoodTVI" TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid x:Name="gChildren">
Adding my TreeViewItem-Style to my TreeView
TVVerlauf.SetBinding(TreeView.ItemContainerStyleProperty, "GoodTVI");
The Rest of the Style stays exactly the same. This is the only difference but the Result looks completley different.
I give my Style a Name
Actually, you don't.
<Style x:Key="GoodTVI" TargetType="TreeViewItem">
...
That's not a name. That's a key. The Style is a resource. Resources have keys, not names. The two are different. For one thing, resource keys are objects rather than strings. And they're looked up differently, in different places.
Here, you're binding the treeview's ItemContainerStyle property to the GoodTVI property of its DataContext (which should be your viewmodel).
TVVerlauf.SetBinding(TreeView.ItemContainerStyleProperty, "GoodTVI");
Since GoodTVI is a resource key, not the name of a property on the viewmodel, you're naturally not getting good results.
Try this on your TreeView in the XAML:
<TreeView
ItemContainerStyle="{StaticResource GoodTVI}"
...other properties...
>
If you need to do this in C#, try this:
TVVerlauf.ItemContainerStyle = (DataTemplate)TVVerlauf.FindResource("GoodTVI");
Try this:
TVVerlauf.SetBinding(TreeView.StyleProperty, "GoodTVI");

Wpf Button Style is not applied

I have a window that has tow group boxes, each group box has 3 buttons, all of the buttons apply the 3 styles. the styles is:
<Style x:Key="SaveButtonStyle" TargetType="Button" >
<Setter Property="Content">
<Setter.Value>
<DockPanel>
<Image Source="/SalesSolution;component/Images/save.png" Stretch="UniformToFill" Height="40" Width="40" VerticalAlignment="Center" />
<Label Content="Save" HorizontalAlignment="Right" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalContentAlignment="Center" FontSize="16" />
</DockPanel>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="100"/>
</Style>
<Style x:Key="UpdateButtonStyle" TargetType="Button" >
<Setter Property="Content">
<Setter.Value>
<DockPanel>
<Image Source="/SalesSolution;component/Images/Refresh_font_awesome.png" Stretch="UniformToFill" Height="40" Width="40" VerticalAlignment="Center" />
<Label Content="Update" HorizontalAlignment="Right" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalContentAlignment="Center" FontSize="16" />
</DockPanel>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="100"/>
</Style>
<Style x:Key="DeleteButtonStyle" TargetType="Button" >
<Setter Property="Content">
<Setter.Value>
<DockPanel>
<Image Source="/SalesSolution;component/Images/delete.png" Stretch="UniformToFill" Height="40" Width="40" VerticalAlignment="Center" />
<Label Content="Delete" HorizontalAlignment="Right" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalContentAlignment="Center" FontSize="16" />
</DockPanel>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="100"/>
</Style>
The buttons' XAML code:
//These three buttons do not applied the styles:
<Button HorizontalAlignment="Left" Name="buttonCompanySave" VerticalAlignment="Center" Click="buttonCompanySave_Click" Margin="188,215,0,323" Style="{StaticResource SaveButtonStyle}" />
<Button HorizontalAlignment="Left" Name="buttonCompaniesUpdate" VerticalAlignment="Center" Click="buttonCompanyUpdate_Click" Margin="188,274,0,264" Style="{StaticResource UpdateButtonStyle}" />
<Button HorizontalAlignment="Left" Name="buttonCompanyDelete" VerticalAlignment="Center" Click="buttonCompanyDelete_Click" Margin="188,333,0,205" Style="{StaticResource DeleteButtonStyle}" />
//These three buttons apply the styles:
<Button HorizontalAlignment="Left" Name="buttonItemSave" VerticalAlignment="Bottom" Click="buttonItemSave_Click" Style="{StaticResource SaveButtonStyle}" />
<Button HorizontalAlignment="Center" Name="buttonItemsUpdate" VerticalAlignment="Bottom" Click="buttonItemsUpdate_Click" Style="{StaticResource UpdateButtonStyle}" />
<Button HorizontalAlignment="Right" Name="buttonItemDelete" VerticalAlignment="Bottom" Click="buttonItemDelete_Click" Style="{StaticResource DeleteButtonStyle}" />
The strange problem is: if I move the blank buttons(buttonCompanySave,buttonCompaniesUpdate,buttonCompanyDelete) to the other group box, they apply the styles !. I try to figure out this problem but I don't find the solution, I even create new group boxes and buttons.
It happens cause your style changes Content property and when you set new Content value, then default style of Button is applied which does not have any Image and Label.
Instead of this you should create ContentPresenter for setting Content property dynamically and create your Image near the ContentPresenter. In addition, to exclude multiple Style's you can use DataTrigger to change Source of Image. Please, see the following example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Background" Value="#ffffff"/>
<Setter Property="BorderBrush" Value="#cccccc"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="#333333"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="16,3,16,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="Chrome" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
<StackPanel>
<TextBlock x:Name="txtBlck" Text="Update"/>
<Image x:Name="img">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Content, ElementName=Presenter}" Value="Update">
<Setter Property="Source" Value="/SalesSolution;component/Images/update.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Content, ElementName=Presenter}" Value="Save">
<Setter Property="Source" Value="/SalesSolution;component/Images/save.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Content, ElementName=Presenter}" Value="Delete">
<Setter Property="Source" Value="/SalesSolution;component/Images/delete.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ContentPresenter Name="Presenter" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#333333" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#dddddd" />
<Setter Property="BorderBrush" Value="#cccccc" />
<Setter Property="Foreground" Value="#333333" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#1ba1e2" />
<Setter Property="BorderBrush" Value="#1ba1e2"/>
<Setter Property="Foreground" Value="#ffffff"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter TargetName="Chrome" Property="BorderBrush" Value="#1ba1e2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
#StepUp: I Updated your code then it is working fine now:
<Image x:Name="img" Stretch="Uniform" StretchDirection="Both">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=txtBlck}" Value="Update">
<Setter Property="Source" Value="/SalesSolution;component/Images/update.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Text, ElementName=txtBlck}" Value="Save">
<Setter Property="Source" Value="/SalesSolution;component/Images/save.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Text, ElementName=txtBlck}" Value="Delete">
<Setter Property="Source" Value="/SalesSolution;component/Images/delete.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
If you have not: Move your button styles into App.xaml.
Or at least into the resource section of the window:
<Window ... >
<Window.Resources>
<!--Your button styles:-->
</Window.Resources>
</Window>

Categories