I have below WPF UserControl:
<UserControl x:Class="myComponents.UI.TextBoxWithPlaceholder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:pEp.UI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Loaded="UserControl_Loaded">
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:TextBoxWithPlaceholder}}"
Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="myCustomTextBox"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
Padding="5"
IsReadOnly="{Binding IsReadOnly}"
HorizontalAlignment="Stretch"
TextChanged="CustomTextBox_TextChanged"
GotFocus="CustomTextBox_GotFocus"
LostFocus="CustomTextBox_LostFocus"
Margin="5"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
<TextBlock Name="myPlaceholderTextBlock"
IsHitTestVisible="False"
Padding="5"
Text="{Binding Placeholder}"
HorizontalAlignment="Left"
Foreground="DarkGray"
Margin="5">
</TextBlock>
</Grid>
</UserControl>
Basically it is a TextBox with a placeholder.
Now from a WPF view I reuse this component by doing:
xmlns:ui="clr-namespace:myComponents.UI"
and then place it as a normal control:
<ui:TextBoxWithPlaceholder Name="myNewTextBox" IsReadOnly="{Binding IsReadOnly}"
Style="{StaticResource myTextBoxStyle}"
Placeholder="please, enter something here"/>
Now as you see above I set a custom style for it:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
Now in my "myNewTextBox" control I am trying to override some inherited properties for the controls named myCustomTextBox and myPlaceholderTextBlock such as Margin, Padding, Background, Foreground, BorderBrush, etc. but I have tried above style and it is not working. Also I have tried:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="{Binding Path=Margin, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Margin, ElementName=myPlaceholderTextBlock }" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myPlaceholderTextBlock }" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="{Binding Path=Background, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=Foreground, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=BorderBrush, ElementName=myCustomTextBox}" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
If you want to be able to set properties of the myCustomTextBox
from view that consumes your TextBoxWithPlaceholder
control, you should add dependency properties to the latter and bind to them in TextBoxWithPlaceholder.xaml and set them in the consuming view, e.g.:
<ui:TextBoxWithPlaceholder ....PlaceHolderMargin="10" />
TextBoxWithPlaceholder.xaml:
<TextBlock Name="myPlaceholderTextBlock"
...
Margin="{Binding PlaceHolderMargin,RelativeSource={RelativeSource AncestorType=UserControl}}">
I am afraid you cannot refer to ElementName=myPlaceholderTextBlock
from a namescope outside the TextBoxWithPlaceholder
control so trying to do this in a Style
that's defined in a consuming view won't work.