Custom Implicit style for WPF Toolkit WatermarkTextBox - wpf

From here it seems possible to create a custom implicit style for WpfToolkit IntegerUpDown control.
<Style TargetType="xctk:IntegerUpDown"
BasedOn="{StaticResource {x:Type xctk:IntegerUpDown}}">
I cannot seem to create a custom implicit style for WpfToolkit WatermarkTextBox though. I have tried this but it does not compile:
<ResourceDictionary xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" ...>
<Style TargetType="xctk:WatermarkTextBox"
BasedOn="{StaticResource {x:Type xctk:WatermarkTextBox}}">...</Style>
Produces error:
Failed to create a 'TargetType' from the text 'xctk:WatermarkTextBox'
Also tried:
<Style TargetType="{x:Type Control}" BasedOn="{StaticResource BaseStyle}" x:Key="WatermarkBaseStyle">
<Setter Property="FontSize" Value="24" />
</Style>
<Style TargetType="{x:Type xctk:WatermarkTextBox}" BasedOn="{StaticResource WatermarkBaseStyle}"/>
Produces error:
'Failed to create a 'Type' from the text 'xctk:WatermarkTextBox'.'

The following works for me:
<Style TargetType="{x:Type xctk:WatermarkTextBox}"
BasedOn="{StaticResource {x:Type xctk:WatermarkTextBox}}">
Try using the x:Type markup extension in both the TargetType and BasedOn properties.

Related

Deriving style from base style fails WPF

I just realized that deriving from default style fails in my WPF app and I have no idea, why. Actually it works, but only due to "Hot reload". So I have:
<Style TargetType="ComboBox" x:Key="TestStyle" BasedOn="{StaticResource {x:Type ComboBox}}"/>
<Style TargetType="ComboBox">
<Setter Property="Width" Value="100"/>
</Style>
in resource dictionary, and:
<ComboBox Style="{StaticResource TestStyle}">
<ComboBoxItem>test</ComboBoxItem>
<ComboBoxItem>I want to cry with blood</ComboBoxItem>
</ComboBox>
in my control. When I start app I see following:
And when I remove BasedOn="{StaticResource {x:Type ComboBox}}" and add it again, I have correct view:
What can be a reason of such behavior? Seems like WPF bug, but I don't think this is possible
To find correct style you need to define it before "TestStyle"
<Style TargetType="ComboBox">
<Setter Property="Width" Value="100"/>
</Style>
<Style TargetType="ComboBox" x:Key="TestStyle" BasedOn="{StaticResource {x:Type ComboBox}}"/>

WPF Style BasedOn not working as expected

Why do my Radiobutton not look like a togglebutton?
Take a look at the code
<Style x:Key="ButtonBaseStyle" TargetType="{x:Type ButtonBase}">
<Setter Property="Height" Value="100" />
</Style>
<Style BasedOn="{StaticResource ButtonBaseStyle}" TargetType="{x:Type Button}" />
<Style BasedOn="{StaticResource ButtonBaseStyle}" TargetType="{x:Type ToggleButton}" />
<Style BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type RadioButton}" />
<StackPanel>
<Button>Button</Button>
<ToggleButton>Toggle</ToggleButton>
<RadioButton>Radio</RadioButton>
</StackPanel>
If I remove the buttonbase style it works
The looks of your RadioButton is not as ToggleButton cause of you have now changed the style hierarchy of ButtonBase->ToggleButton->RadioButton (the order in which styles and templates are overwritten in derived classes of WPF).
Your new hierarchy of style gives the most priority to the style of ButtonBase. So you have a new ToggleButton style that is derived from a ButtonBase and then you overwrite the RadioButton style with that. So noone can tell you for sure which properties have you overwritten and which will be the final set of properties.
To understand this change the XAML as following:
<Style BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type ToggleButton}" />
<Style BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type RadioButton}" />
and now see the look & feel of your RadioButton.
I'm not clarifying what is exactly happened and why your ToggleButton is not affected so much.
But as I said it's all about the style hierarchy which is build for a control at last just before rendering on the UI.

Defining default layout properties

I want to set consistent margins throughout all controls within an entire view. I currently use XAML:
<Window.Resources>
<Thickness x:Key="ConsistentMargins">0,10,0,0</Thickness>
</Window.Resources>
<!-- ... -->
<!-- ... -->
<!-- ... -->
<MyControl1 Margin="{StaticResource ConsistentMargins}">
<MyControl2 Margin="{StaticResource ConsistentMargins}">
<MyControl3 Margin="{StaticResource ConsistentMargins}">
Is there a way to set a default layout style for controls to avoid the above repeated code shown above?
You can create your own style with TargetType and this style will be assigned to all object of type which you specified in TargetType. But in this case your created style will be applied only for speciefied type of object, but not for derived type.
E.g. you can create style for all buttons like this:
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0,10,0,0" />
</Style>
I think that this makes sense that style is not applied from base class, because I want say "My all buttons looks like...", but I want not say "Everything looks like...".
You may create a base default style, perhaps for FrameworkElement, and let the default styles for other element types extend the base style:
<Window.Resources>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type FrameworkElement}}"/>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type FrameworkElement}}"/>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type FrameworkElement}}"/>
...
</Window.Resources>

Overriding single property setter from ResourceDictionary

I have a style defined in a file called MyStyles.xaml:
<Style TargetType="{x:Type igDP:XamDataGrid}">
<Setter Property="FontSize" Value="10" />
<Setter Property="FontFamily" Value="Arial" />
<EventSetter Event="CellUpdating" Handler="grid_CellUpdating"/>
</Style>
In one of my views, I have a XamDataGrid defined:
<igDP:XamDataGrid>
<igDP:XamDataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyProject.TheViews;component/Views/MyStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type igDP:XamDataGrid}" BasedOn="{StaticResource {x:Type igDP:XamDataGrid}}">
<Setter Property="FontSize" Value="70"/>
</Style>
</ResourceDictionary>
</igDP:XamDataGrid.Resources>
Basically, I want to keep everything that is defined in the style for XamDatagrid in MyStyles.xaml except for the font size, which I want to be set to 70.
I can't seem to get it to work. With the above, the font is set to 70 but I lose the other settings that are defined in MyStyles (such as the event handling and font family).
What am I doing wrong here?
(Extracting an answer from comments above.)
For overriding the style, I would suggest the following:
Define 2 styles in MyStyles.xaml: a named one which contains the style, and the unnamed one (this will be the default style) simply based on the named one
<Style x:Key="XamDataGridDefaultStyle" TargetType="{x:Type igDP:XamDataGrid}">
<Setter Property="FontSize" Value="10" />
<Setter Property="FontFamily" Value="Arial" />
<EventSetter Event="CellUpdating" Handler="grid_CellUpdating"/>
</Style>
<Style TargetType="{x:Type igDP:XamDataGrid}"
BasedOn="{StaticResource XamDataGridDefaultStyle}"/>
This will define the needed default style for all the views.
For the resources of the view where the customization is needed, define the following override:
<Style TargetType="{x:Type igDP:XamDataGrid}"
BasedOn="{StaticResource XamDataGridDefaultStyle}">
<Setter Property="FontSize" Value="70"/>
</Style>
You'll perhaps need to reference MyStyles.xaml as merged dictionary in the resources of the customized view for StaticResource to work.

WPF style causing loop

Why does the following XAML cause a stack overflow exception with some themes?
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ExpressionLight.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="5"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}"/>
</ResourceDictionary>
</Application.Resources>
I have tried several themes found on internet and about half of them causes the exception.
Is there another way to apply a named Style as default?
Edit:
The problem is that the Theme adds the default style to the resource dictionary (an entry with the name System.Windows.Control.Button). Since a dictionary can only contain a single entry for each key it is not possible add a new default within the same resource dictionary.
Don't know why it leads to a "stackoverflow" instead of a "duplicate key" exception. It is probably because of the special handling of merged dictionaries which can contain duplicate keys.
The solution is to apply the named Style as default in code:
void AppStartup(object sender, StartupEventArgs args) {
this.Resources[typeof(Button)] = this.Resources["BaseButtonStyle"];
....
}
Since the BaseButtonStyle is staticly bound to the theme it is of course not possible to change theme at runtime with this solution.
you are having circular dependency in this code:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="5"/>
</Style>
this style says that it is for TargetType Button, thats fine.
it also says that it is BasedOn the Style defined for TargetType Button, which is this itself.
Better to assign a key to the previous Style and then use that key in BasedOn.
EDIT:
After going through your code again it seems that there is a circular reference between your style and the style defined in ExpressionLight.xaml. A workaround would be to place resources at different levels.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ExpressionLight.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.Resources>
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="5"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}"/>
</Grid.Resources>
............
...........
...........
</Grid>

Resources