WPF reference style in resource dictionary and use triggers - wpf

I have a Style defined in a resource dictionary that applies to
all ComboBox controls. Within the ComboBox control, I reference the style like so:
Style="{DynamicResource MyComboBoxStyle}"
This works ok.
I want to be able to add some triggers to some of the ComboBox controls.
What is a good way to use the Style referenced as a dynamic resource yet still be able to add Triggers to some of the ComboBox controls?

Update:
After re-reading the question, I realize this isn't exactly what the OP was asking about. I could delete this, but perhaps it will be useful to someone who stumbles upon this question.
Here's an example, with a xaml resource dictionary defining the template and the triggers, along with a window that references that resource and applies the style.
It may help someone looking into using templates and triggers:
My resource named "Style1.xaml"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="TonyTemplate" TargetType="Button">
<Border Name="Border"
BorderBrush="Orange"
BorderThickness="3"
CornerRadius="2"
Background="Ivory"
TextBlock.Foreground="Black">
<Grid>
<ContentPresenter RecognizesAccessKey="True"
Margin="{TemplateBinding Padding}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="Yellow" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="Chartreuse" />
<Setter TargetName="Border" Property="BorderBrush" Value="DarkKhaki" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
My MainWindow Code xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Width="100" Height="50"
Template="{StaticResource TonyTemplate}"
Content="Click me"/>
</Grid>
</Window>

Create new styles for the ComboBox controls that you want to apply triggers to, and use the BasedOn property on the new style to set their base style.

Related

Apply a style to all textbox in my WPF application

I am having an issue while I want to apply a style (font size) to all my textbox, where ever they are.
I, of course found those links :
Apply an application-level style to all textboxes
How to target all controls (WPF Styles)
But this doesn't work for me.
The first one is still better because you don't need to use a key, and going to all your textbox.
I already have, in my app.xml, style applying to all controls (applying a color), so I tried something like this (even if this won't really be enough for me, since those styles are not everywhere) :
<Style x:Key="Type1Data" TargetType="{x:Type Control}">
<Setter Property="Background" Value="#FEE9E6"/>
<Style.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="50" />
</Style>
</Style.Resources>
</Style>
And as I said, I tried this too, but won't work.
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="50" />
</Style>
Any idea what is my probleme and how I can achieve what I want to?
All the hings I can find make me come back to the same code, and didn't found one that works.
edit : here is my current app.xaml
<Application x:Class="myApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:myApp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="TextBox"><!-- tried adding those 3 lines too-->
<Setter Property="FontSize" Value="50"/>
</Style>
<Style x:Key="Type1Data" TargetType="{x:Type Control}">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style x:Key="Type2Data" TargetType="{x:Type Control}">
<Setter Property="Background" Value="White"/>
</Style>
<Style x:Key="Type3Data" TargetType="{x:Type Control}">
<Setter Property="Background" Value="Green"/>
</Style>
</Application.Resources>
</Application>
As I said, the current styles does not cover the whole app (I add the key that is needed, or nothing)
edit : and if I add directly (as a second setter) font size to the Type 1,2 or 3, the font size apply. So it seems, there is no oter styles that are applying besides the 3 in app.xml.
<Setter Property="FontSize" Value="50" />
Sample of code who should get a different textbox size(one with already a style, one without), they are in grid:
<com:ViewControl x:Class="myApp.View.ViewControl"
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:syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:input="http://schemas.syncfusion.com/wpf"
xmlns:local="clr-namespace:myApp.View"
xmlns:com="clr-namespace:RAPINF.PLL.Common;assembly=myApp.Common"
xmlns:entities="clr-namespace:myApp.Entities;assembly=myApp.Entities"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="700">
<TextBox Style="{StaticResource Type1Data}" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Margin="2" Text="{Binding Data.Name}" VerticalAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="2" Text="{Binding Data.Name}" VerticalAlignment="Center" Grid.ColumnSpan="3" />
edit : adding the code of the popup I use sometimes and works
<sf:RibbonWindow x:Class="namespace:myApp.Common.DetailViewWindow"
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:sf="http://schemas.syncfusion.com/wpf"
xmlns:self="clr-namespace:myApp.Common"
mc:Ignorable="d"
d:Height="300" d:Width="400"
WindowStartupLocation="CenterOwner"
>
</sf:RibbonWindow>
How my usercontrol is added to the dock :
public void AddView(UserControl View, string sTitle, DockState docState)
{
int Width = 800;
int Height = 400;
DockingManager.SetHeader(View, sTitle);
DocumentContainer.SetMDIBounds(View, new Rect(30, 30, Width, Height));
DockingManager.SetState(View, docState);
DockingManager.SetShowCloseMenuItem(View, true);
DockingManager.SetDesiredWidthInDockedMode(View, Width);
DockManager.Children.Add(View);
ActivateView(View);
}
If I use the dock I do this before :
ApplicationContext.Current.AddView(View, DockState.Document);
ANd with a popup, almost the same :
DetailViewWindow dlg = new DetailViewWindow(View);
dlg.ShowDialog();
As, those two code are used with the same View (yes, exactly the same), then I guess the problem comes from the fact of adding the view in the dock, and not in a popup window.
Does the dock manager forces me to use a key?
Thank you for your help.
I can't reproduce your problem. I can just show you a working example. Maybe it's helping you finding your problem.
App.xaml
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize"
Value="50" />
</Style>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="WpfApplication2.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow"
Name="MyWindow"
SizeToContent="WidthAndHeight">
<TextBox Width="150"/>
</Window>
Output
I too had no problem with the styling. But I typically break my stuff into separate dictionaries for different controls and derive from some of my own classes. I also define a style and assign a "x:Key" name to it. This is like saying I have a class with this key name and I want it to look like this. Then, once I get it working, I take the final class and say use your style based on the key defined... Having said that, Here is a stripped basic of the App.xaml
<Application.Resources>
<Style TargetType="TextBox" x:Key="STextBox">
<Setter Property="FontSize" Value="50"/>
<Setter Property="FontFamily" Value="WingDings" />
</Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource STextBox}" />
</Application.Resources>
I can define all sorts of things about my base-style "STextBox" (via the x:Key). But after, I set the style with a target BASED ON the style via x:Key. The critical thing I think you were missing is the target must be of {x:Type TextBox}.
If you look at the xmlns headers at the top such as
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
the "x=" is the alias of the library it is getting control types. By you generically declaring the
TargetType="TextBox"
You are not specifically associating to the CLASS TYPE.
Then in my main window (and anywhere else in the app), I have this in my main grid
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="80" />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="Testing" />
<TextBox Grid.Row="1" Text="Another Line" />
<TextBox Grid.Row="2" Text="Last" />
</Grid>
and they all work properly. You can also change default colors, size, font family, margins, etc to the base style and all will change without explicit reference to every control.

Possible to create an implicit style that is used, by default, as the base for other styles?

I'm trying to figure out a way to create an implicit style for a custom control, that will be inherited by other styles applied to the control.
For example, let's say I have a control FancyButton. Then I can define an implicit style by putting this in my app resources:
<Style TargetType="my:FancyButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="my:FancyButton">
<TextBlock Text="hello world" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then users of the control will see "hello world" in green just by writing:
<my:FancyButton Foreground="Green" />
The problem is, if someone wants to define a green-colored style like this ...
<Style TargetType="my:FancyButton" x:Key="GreenButton">
<Setter Property="Foreground" Value="Green" />
</Style>
<my:FancyButton Style="{StaticResource GreenButton}" />
... then they will have lost the implicit style's control template, and will not see the "hello world".
Of course, you can define a base style, which the implicit style inherits ...
<Style TargetType="my:FancyButton" x:Key="FancyButtonDefaultStyle">
<!-- ... -->
</Style>
<Style TargetType="my:FancyButton" BasedOn="{StaticResource FancyButtonDefaultStyle}">
</Style>
... and that way users of the control can inherit the default style:
<Style TargetType="my:FancyButton" x:Key="GreenButton" BasedOn="{StaticResource FancyButtonDefaultStyle}">
<Setter Property="Foreground" Value="Green" />
</Style>
But it seems awkward to force users of the control to remember to inherit a default style based on a key. Isn't there some way to make a custom control's styles inherit the implicit style, in the same way that the framework controls do?
Ie, I want my FancyButton to behave in the same way a Button does, where I can define a style that doesn't wipe out the other default style properties (esp. ControlTemplate):
<Style TargetType="Button" x:Key="GreenButton">
<Setter Property="Foreground" Value="Green" />
</Style>
You need to put the implicit style definition
<Style TargetType="my:FancyButton">
<!-- etc -->
</Style>
in the special "Themes/Generic.xaml" resource dictionary (in the same assembly as where the control class is defined). This makes all styles inherit from the implicit style, as you wanted.
Sorry for quoting. :)
Hope this helps.
Here's my code:
MainPage.xaml:
<UserControl x:Class="SilverlightApplication4.MainPage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SilverlightApplication4"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="local:TemplatedControl1"
x:Key="myCustomTemplate">
<Setter Property="Foreground"
Value="Purple" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot"
Background="Yellow"
Width="500"
Height="500">
<local:TemplatedControl1 Style="{StaticResource myCustomTemplate}" />
</Grid>
</UserControl>
Now in TemplatedControl.cs don't forget to put this:
this.DefaultStyleKey = typeof(TemplatedControl1);
And finally put your implicit style definition in Themes\Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SilverlightApplication4">
<Style TargetType="local:TemplatedControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TemplatedControl1">
<TextBlock Text="hello world"
Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
With this method, the result should be purple text in a terrible yellow background. :)
Thanks to #Tanis83 for pointing out the (very simple) answer. I just needed to put the implicit style ...
<Style TargetType="my:FancyButton">
<!-- etc -->
</Style>
in the special "Themes/Generic.xaml" resource dictionary (in the same assembly as where the control class is defined). This makes all styles inherit from the implicit style, as I wanted.

Pin Toggle button style

Hi i want to create a generic style for pin button.
<Window x:Class="TooglePinButtonStyle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Image x:Key="pinImage"
Width="14"
Height="14"
Source="/TooglePinButtonStyle;component/Images/pin.png" />
<Image x:Key="unPinImage"
Width="14"
Height="14"
Source="/TooglePinButtonStyle;component/Images/unpin.png" />
<Style x:Key="pinButtonStyle"
TargetType="{x:Type ToggleButton}">
<Setter Property="Content" Value="{DynamicResource unPinImage}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="{DynamicResource pinImage}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ToggleButton Height="30"
Width="30"
Style="{StaticResource pinButtonStyle}"/>
<ToggleButton Height="30"
Width="30"
Style="{StaticResource pinButtonStyle}"/>
</StackPanel>
</Window>
It works fine when there is only one button but when I have two button the UI crashes with
"Specified element is already the logical child of another element.
Disconnect it first."
exception.
Either make the images non-shared, or set the ContentTemplate to some DataTemplate which contains an image (not a reference to an image), rather than the Content. If you have only one instance of an UI-element you will run into this problem, templates describe what should be created rathen than using instances directly.

Mouseover border in a custom control for a textblock

I am trying to create a custom control for a text block that when moused over, a border will appear. I am pretty new to WPF and have only made some very simple custom controls. I need to implement this in a XAML UserControl.
Any suggestions would be greatly appreciated. Thanks again, StackOverflow.
EDIT: I am going to have to bind a persistence property to several different controls, so I really need to do this in a custom control. This is what I have, and it isn't working:
xmlns:customControls="clr-namespace:****.CustomControls"
....
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
And the UserControl:
<UserControl
x:Class="****.MouseOverBorder"
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"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="MouseOverBorder" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="3" />
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Border Style="{DynamicResource MouseOverBorder}" BorderThickness="1" CornerRadius="3" SnapsToDevicePixels="True"/>
No need to make a UserControl. I've managed to accomplish this with the following markup:
<Border Style="{DynamicResource BorderStyle1}" BorderThickness="1" CornerRadius="3" >
<TextBlock Text="TextBlock" />
</Border>
Here's the style:
<Style x:Key="BorderStyle1" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="3"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#FF123BBA"/>
</Trigger>
</Style.Triggers>
</Style>
EDIT:
Still don't get it why do you need a UserControl (please don't call it custom control - these are different things), but let's consider your example.
When you write the following
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
you are actually setting MouseOverBorder.Content property. Originally it's Content is defined in MouseOverBorder.xaml file. So you are replacing all your UserControl structure with TextBlock. But still I got your idea and have solution for it.
First, add custom DependencyProperty and CLR wrapper for it to MouseOverBorder class:
public static readonly DependencyProperty MyContentTemplateProperty =
DependencyProperty.Register("MyContentTemplate", typeof(DataTemplate), typeof(MouseOverBorder), null);
[Browsable(true)]
[Category("Other")]
public DataTemplate MyContentTemplate
{
get { return (DataTemplate)GetValue(MyContentTemplateProperty); }
set { SetValue(MyContentTemplateProperty, value); }
}
Second, make something inside MouseOverBorder use this property, e.g.
<ContentPresenter ContentTemplate="{Binding MyContentTemplate, ElementName=userControl}"/>
<!-- userControl is the Name of MouseOverBorder, defined in xaml -->
At last, you can use your UserControl as following:
<customControls:MouseOverBorder>
<customControls:MouseOverBorder.MyContentTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</DataTemplate>
</customControls:MouseOverBorder.MyContentTemplate>
</customControls:MouseOverBorder>

Accessing ListBox DisplayMemberPath data value in SelectedItem template

I am attempting to create a generic ListBox control to customize edit in place as well as other features.
In the example below, I want to bind the "Text" property of the ListBox "selected item" to the data value of the DisplayMemberPath in the viewed structure. Such XAML binding expression would replace the question marks in the code (Text="{Binding ????????????????").
Using a ContentPresenter instead of binding the text works for display purposes, but I have not been able to bind to the Text component used on the presenter. An alternative to finding the binding expression is to be able to get the Text content from the ContentPresenter.
I can think of a number of ways to accomplish this through code behind, but I am looking for a XAML solution if such thing exists.
I appreciate any ideas. I am almost sure there is a trivial answer to this, but after spending a couple days on it, I admit a nudge in the right direction would greatly help me.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<XmlDataProvider x:Key="NobelLaureatesInPhysics"
XPath="/NobelLaureatesInPhysics">
<x:XData>
<NobelLaureatesInPhysics xmlns="">
<NobelLaureate>
<ID>1</ID>
<Name>Wilhelm Röntgen</Name>
<AwardDate>12/10/1901</AwardDate>
</NobelLaureate>
<NobelLaureate>
<ID>2</ID>
<Name>Hendrik Lorentz</Name>
<AwardDate>12/10/1902</AwardDate>
</NobelLaureate>
<NobelLaureate>
<ID>3</ID>
<Name>Pieter Zeeman</Name>
<AwardDate>12/10/1902</AwardDate>
</NobelLaureate>
</NobelLaureatesInPhysics>
</x:XData>
</XmlDataProvider>
<ControlTemplate x:Key="ItemTemplate"
TargetType="ListBoxItem">
<TextBlock Foreground="Black">
<ContentPresenter />
</TextBlock>
</ControlTemplate>
<ControlTemplate x:Key="SelectedItemTemplate"
TargetType="ListBoxItem">
<TextBox Background="Black"
Foreground="White"
Text="{Binding ????????????????"/>
</ControlTemplate>
<Style TargetType="{x:Type ListBoxItem}"
x:Key="ContainerStyle">
<Setter Property="Template"
Value="{StaticResource ItemTemplate}" />
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Template"
Value="{StaticResource SelectedItemTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="TestListBoxStyle"
TargetType="{x:Type ListBox}">
<Setter Property="ItemContainerStyle"
Value="{DynamicResource ContainerStyle}" />
</Style>
</Window.Resources>
<Grid>
<ListBox Style="{DynamicResource TestListBoxStyle}"
ItemsSource="{Binding Source={StaticResource NobelLaureatesInPhysics}, XPath=NobelLaureate}"
DisplayMemberPath="Name"/>
</Grid>
{Binding Path=DisplayMemberPath, RelativeSource={RelativeSource Mode=FindAncestor, Type={x:Type ListBox}}
That should work

Resources