I've customized my projects TextBox via a ResourceDictionary.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Style x:Key="TextBoxTheme" TargetType="{x:Type TextBox}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border CornerRadius="10"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="2"
Background="#FF62B6CB">
<Grid>
<TextBox VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
Padding="5,0,5,0"
Background="Transparent"
BorderThickness="0"
Foreground="#1B4965"
Margin="1"
TextWrapping="Wrap"
FontWeight="Bold"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextWrapping" Value="Wrap" />
</Style.Setters>
</Style>
now I'm trying to add the same design to the Passwordbox
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Style x:Key="PasswordBoxTheme" TargetType="{x:Type PasswordBox}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Border CornerRadius="10"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="2"
Background="#FF62B6CB">
<Grid>
<PasswordBox VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
Padding="5,0,5,0"
Background="Transparent"
BorderThickness="0"
Foreground="#1B4965"
Margin="1"
FontWeight="Bold" />
<!--Password="{Binding RelativeSource= {RelativeSource TemplatedParent}, Path=Password, UpdateSourceTrigger=PropertyChanged}"/-->
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
The Problem I'm having is that the Password Property of my Passwordbox is empty even though I entered a password. How can I access the Password?
WPF does not bind to the Password proptery of the PasswordBox in fact internally, but always to a DependencyProperty with the name "< nameYouSpecified >Property". If you look at the PasswordBox class there are some DependencyProperties.
For examle:
public static readonly DependencyProperty CaretBrushProperty;
But you will not find a
public static readonly DependencyProperty PasswordProperty;
where WPF could bind to.
Long story short: The Password is not bindable.
Related
The code below does not align the text to right. If I do not use Window.Resources (I want to change color of the selected item) code works. Can you help me please?
<Window.Resources>
<Style x:Key="_ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="_Border"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="_Border" Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ListBox x:Name="myListBox" ItemContainerStyle="{DynamicResource _ListBoxItemStyle}" Margin="0,20,0,30"
VerticalAlignment="Top" Width="800" HorizontalAlignment="Right" MinHeight="200" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionChanged="myListBox_SelectionChanged" MouseDoubleClick="myListBox_MouseDoubleClick" Panel.ZIndex="2"
BorderThickness="0" FontSize="15" Background="{x:Null}"
HorizontalContentAlignment="Right">
</ListBox>
You are replacing the ListBoxItem ControlTemplate, and your template ignores the HorizontalContentAlignment property:
Fix:
<ControlTemplate TargetType="ListBoxItem">
<Border Name="_Border"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
Try to set the style property for your item otherwise the resources window that you create will set it for you.
By doing this I was able to achieve your desire (maybe it is a bit tricky) :
<ListBox x:Name="myListBox" ItemContainerStyle="{DynamicResource _ListBoxItemStyle}" Margin="0,20,0,30"
VerticalAlignment="Top" Width="800" HorizontalAlignment="Right" MinHeight="200" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Panel.ZIndex="2"
BorderThickness="0" FontSize="15" Background="{x:Null}"
HorizontalContentAlignment="Right">
<ListBoxItem>
<TextBlock HorizontalAlignment="Right" Text="Test"></TextBlock>
</ListBoxItem>
</ListBox>
So this is my XAML and for some reason it's not changing colors on mouseover, I added the triggers for it and I thought that would do it, when I hover over the button its not doing anything at all, why is that?
<Button Click="ButtonBase_OnClick" Margin="10,0,0,0" Style="{DynamicResource RoundedButtonStyle}" Width="100" Height="30" HorizontalAlignment="Left">
<Grid>
<Image IsHitTestVisible="False" Height="15" Width="15" VerticalAlignment="Center" HorizontalAlignment="Left" Source="Resources/addButton.png" />
<TextBlock IsHitTestVisible="False" Margin="20,0,0,1" VerticalAlignment="Center" Foreground="#9e9e9e">Add Product</TextBlock>
</Grid>
</Button>
<Window.Resources>
<Style x:Key="RoundedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="#2d2d30" BorderThickness="1" Padding="2">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Its not changing because you modified the control template of Button to:
<Border CornerRadius="5" Background="#2d2d30" BorderThickness="1" Padding="2"
Note the hard-coded background color. No matter what you do to the button's Background property it won't take effect since its not used. If you want to use that property in your template you need a TemplateBinding:
Background="{TemplateBinding Background}"
Then in the style set the default to your original value.
<Setter Property="Background" Value="#2d2d30"/>
The Label.Binding outside TextBox.Template does work fine but when I want to bind ViewModel.Value to the TextBox inside TextBox.Template then I always get
Error: 40 : BindingExpression path error: 'ViewModel' property not found on 'object'
Is there a way to set the DataContext inside TextBox.Template to the DataContext from the Parent?
<Style TargetType="{x:Type fields:CustomDateFieldView}">
<Label Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ViewModel.Label}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type fields:CustomDateFieldView}">
....
<TextBox.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ViewModel.Value}"/>
....
</Stackpanel>
</ControlTemplate>
</TextBox.Template>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type fields:CustomDateFieldView}">
<Label Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ViewModel.Label}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type fields:CustomDateFieldView}">
....
<TextBox.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding ViewModel.Value, ElementName = myControlName}"/>
....
</Stackpanel>
</TextBox.Template>
If you give an x:Name to your CustomDateFieldView control, you can use this approach. In my example i put as ElementName myControlName. This require that myControlName.DataContext is your viewmodel of course
EDIT: if the first approach doesn't work, you can try this:
<Style TargetType="{x:Type fields:CustomDateFieldView}">
<Label Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ViewModel.Label}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type fields:CustomDateFieldView}">
....
<TextBox.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding ViewModel.Value, RelativeSource={RelativeSource AncestorType={x:Type fields:CustomDateFieldView}}}"/>
....
</Stackpanel>
</TextBox.Template>
I have the following HeaderTemplate for an Expander:
<Expander.HeaderTemplate>
<DataTemplate>
<Grid Background="#939393">
<Grid.RowDefinitions>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" CornerRadius="5,5,5,5"
Background="Transparent" BorderBrush="#FF000000" Margin="1" BorderThickness="1,1,1,1" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="DarkGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Background="#6E6E6E"/>
<ToggleButton Grid.Column="0" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}}" Focusable="False">
<Image Source="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}, Converter={StaticResource boolToExpanderDirectionConverter}}"/>
</ToggleButton>
<TextBlock Grid.Column="1" Text="General" Margin="5,1,1,1" VerticalAlignment="Top" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Expander.HeaderTemplate>
This Headertemplate I have defined directly at one Expander. Now I want to move this Template to a Resource and apply it to all Expanders. My problem now is, that I don't know how to set the Header of the TextBlock in the Template to the Header of the Expander.
I knwo there's a way with TemplateBinding, but unfortunately I don't know how to use this.
TemplateBinding can only be used within a ControlTemplate.TemplateBinding is used for binding to the element properties within the template definition..
here in your example you have used controltemplate for toggleButton.
Example For TemplateBinding
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter TextElement.Foreground="{TemplateBinding Foreground}" x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
.....
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ToggleButton Grid.Column="0" Background="Red" BorderBrush="Black" BorderThickness="1" Foreground="White"/>
Here Border and Contentpresnter will bind properties of ToggleButton that is alreday defined in its defination.
But in your example you used Datatemplate..so you cant use TemplateBinding ..Please Follow This link for Binding Syntax.
Solution For Your example
Using Binding syntax we can bind Header property to different exapnder
Text="{Binding Path=Header,RelativeSource={RelativeSource AncestorType={x:Type Expander}}}"
<Window.Resources>
<DataTemplate x:Key="ExpanderHeaderTemplate">
<Grid Background="#939393">
<Grid.RowDefinitions>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" CornerRadius="5,5,5,5"
Background="{TemplateBinding Background}" BorderBrush="#FF000000" Margin="1" BorderThickness="1,1,1,1" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="DarkGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Background="#6E6E6E"/>
<ToggleButton Grid.Column="0" Background="Red" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}}" Focusable="False">
<Image Source="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}, Converter={StaticResource boolToExpanderDirectionConverter}}"/>
</ToggleButton>
<TextBlock Grid.Column="1" Text="{Binding Path=Header,RelativeSource={RelativeSource AncestorType={x:Type Expander}}}" Margin="5,1,1,1" VerticalAlignment="Top" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<Expander Header="General1" HeaderTemplate="{StaticResource ExpanderHeaderTemplate}"/>
<Expander Header="General2" HeaderTemplate="{StaticResource ExpanderHeaderTemplate}"/>
</StackPanel>
you can have a idea of Template binding by below code i had implemented this when i was learning XAML.
<Button Template="{DynamicResource CircleButton}" Background="Green" Content="1"></Button>
<ControlTemplate x:Key="CircleButton" TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" MinHeight="36" MinWidth="36">
<Ellipse Fill="{TemplateBinding Background}"></Ellipse>
<ContentPresenter TextBlock.FontFamily="Calibri" TextBlock.FontSize="24" TextBlock.Foreground="Wheat" HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
you have to give a x:Key to control Template and when you are binding it with some specific element define that x:key there like i did Template="{DynamicResource CircleButton}".
following is your case:
<Style TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
// Do your thing.
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
this will apply to all Expander throught your application. You can put this Style into App.xaml file for code cleanness. hope this'll help you.
Since you are specifying a HeaderTemplate via a DataTemplate, the DataContext of the template IS the Header. This simple example works:
<Expander Header="Test">
<Expander.HeaderTemplate>
<TextBlock Text="{Binding}"/>
</Expander.HeaderTemplate>
</Expander>
In our WPF application we have a common control template which we use to display errors in a consistent way
<ResourceDictionary>
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderThickness="1" BorderBrush="Red">
<AdornedElementPlaceholder />
</Border>
</ControlTemplate>
</ResourceDictionary>
Elsewhere in our application when a control might display an error we set the ErrorTemplate like so
<TextBox Validation.ErrorTemplate="{DynamicResource ErrorTemplate}" />
I now want to display a tool tip in this error template, however setting the tooltip property on the border doesn't help that much as the tooltip only displays when the user mouses over the 1px wide border, not the control itself which is in error.
I know that I can set the tooltip in a style, however this error template is applied to many different controls (combo boxes etc...) and many of these controls also use styles which are independent from my error template - I really want to be able to apply my error template in a generic way to any control.
Is there any way that I can set a tooltip in my ErrorTemplate?
I have a style defined. I have IDataErrorInfo on my object (Customer) which does the validation for the property(LastName) which is databound to a text box for example. Here's my style:
<Style x:Key="ValidationTextBox" TargetType="{x:Type Control}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,2,40,2"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border Background="#B22222" DockPanel.Dock="Right" Margin="5,0,0,0" Width="20" Height="20" 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="#B22222" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style
<TextBox Style="{StaticResource ValidationTextBox}" Text="{Binding Path=Customer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
As I stated in my answer here you can:
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderThickness="1" BorderBrush="Red"
Background="Transparent"
ToolTip="{Binding Path=/ErrorContent}">
<AdornedElementPlaceholder />
</Border>
</ControlTemplate>
I'm sorry I didn't have time yesterday...Would you try below and see if this is what you are after, please?
<Style x:Key="ValidationTextBox2" TargetType="{x:Type Control}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="2">
<DockPanel LastChildFill="True" ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Background="Transparent">
<TextBlock />
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center">
</AdornedElementPlaceholder>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>