Alter a style from a parent - c#

I have a custom class that is derived from userControl, it describes what features a "service window" should have. It should also describe how a instance of this "service window" should look.
I have a style called serviceStyle. now whenever i create a new instance of the service window, i have to manually set the style in the XAML of the instance, when possible i want to avoid having to do this by basically forcing the style to all childs of service window to serviceStyle. Then i want to be able to do a fade animation on a textBlock in serviceStyle. Now since this is the style of a child of the "Service window" it seems unreachable...
In the meantime i found a way to Set the Style as a default style for all the service windows, this can be done by adding this line in the constructor:
DefaultStyleKeyProperty.OverrideMetadata(typeof(NetcarityService), new FrameworkPropertyMetadata(typeof(NetcarityService)));
Now i need to be able to get from the source to the element textBlock in the xaml of the ServiceWindowStyle....
Thanks in advance.

You don't need to do that in order to make a default style, you just define your style without a key. For example, this style applies to all button in an app (if the style is defined in app.xaml)
<Style TargetType="{x:Type Button}">
<Style.Setters>
<Setter Property="Margin" Value="6"></Setter>
<Setter Property="Padding" Value="6,3,6,3"></Setter>
</Style.Setters>
</Style>
With regards the children I would think you just need to write some code to detect when a child is added and set the default style for the child. I think you can just override OnVisualChildrenChanged.
PS. Setting DefaultStyleKeyProperty should be done in the static constructor

Related

Change Button Foreground in :pointerover and :pressed states

In fluent theme i can't change button Foregrounds in this states. In Github i find this code:
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
...
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style>
But my project can't build with Foreground on ContentPresenter#PART_ContentPresenter.
ContentPresenter does not have a Foreground property. If you target a TextBlock you could use attached property TextBlock.Foreground. If not, there are child and descendant selectors you may want to take look at.
Also the nested selector ^ does not seem to be documented (it's pretty new it seems), maybe it would be safer to just use name of the control (Button in your case) for now.

Apply Style to every element of type X in UWP

I'm currently trying to find a way to style all controls in a UWP app with the same Style/type. To be specific I want to set OpticalMarginAlignment to TrimSideBearings for every - I mean every TextBlock.
I know I can create a Style in App.xaml without x:Key property like this:
<Style TargetType="TextBlock">
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings" />
</Style>
But this does not change the style of TextBlocks which are in a DataTemplate (which according to similar questions is by design). However I don't want to have to set a Style for each TextBlock used in a DataTemplate, so I thought about other solutions:
Create a StyledTextBlock element derived from TextBlock (not working cause TextBlock is sealed)
Create a StyledDataTemplate element derived from DataTemplate (not working cause I haven't found anything in DataTemplate I could hook into to load the Style and because there is no DataTemplate.Resources)
Create a StyledTextBlock element derived from UserControl with a TextBlock element inside
Number 3 is even working, though it would require me to create a DependencyProperty for every TextBlock.DependencyProperty I want to use to style the StyledTextBlock like this:
<StyledTextBlock Text="Example" FontSize="10" />
To keep code amount low I could create a TextStyle DependencyProperty in StyledTextBlock and set it like this, but I don't like this solution as well:
<StyledTextBlock Text="Example">
<StyledTextBlock.TextStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10" />
</Style>
</StyledTextBlock.Style>
</StyledTextBlock>
Does anyone have another idea how to achieve this?

Change the control property globally in wpf

I have a back button which is copied almost to all the Controls in my application.
I have set the styles and properties of the button on each individual control (usercontrol)
Now I want to change the text property of the button of all the control (usercontrol).
I don't want to go and change the property of each control.
Please help me setting a global property which sets the property in one place.
Since the style is common to all pages. Create the style without a key/name, just the target type would do.
<Style TargetType="{x:Type Button}">
Then do either of the following -
Add it to the App.XAML for visibility throughout the app
Better approach would be to define a resource dictionary file and import it, wherever you need it.
<Style TargetType="{x:Type Button}">
<Setter Property="Text" Value="{Binding text}" />
<Setter Property="...." Value="{Binding ....}"/>
</Style>
Add this to App.xaml file as you want it to be global style for all your user controls.

WPF Updating styles at runtime

I would like to update the default Window style dynamically at runtime so I can change the FontSize and FontFamily dynamically at runtime. I found that Styles in your resource dictionary are sealed at runtime and cannot be changed, so I used the following method of updating the style:
<Style TargetType="{x:Type Window}">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="12pt"/>
</Style>
With the following code:
Style newStyle = (Make a copy of the old style but with the FontSize and FontFamily changed)
// Remove and re-add the style to the ResourceDictionary.
this.Resources.Remove(typeof(Window));
this.Resources.Add(typeof(Window), newStyle);
// The style does not update unless you set it on each window.
foreach (Window window in Application.Current.Windows)
{
window.Style = newStyle;
}
There are several problems with this approach and I have a few questions as to why things are the way they are.
Why are styles sealed at runtime and is there a way of making them unsealed?
When I re-add the new style, why is this not picked up by all of my windows? Why do I have to go and manually apply it to every window?
Is there a better way?
I would probably tackle this with a "settings service" which exposes properties for the various settings, and fires INPC as you would for normal binding. Next up I'd change that style to be something like:
<Style x:Key="MyWindowStyle">
<Setter Property="FontFamily" Value="{Binding Path=FontFamily, Source={StaticResource SettingsService}, FallbackValue=Arial}"/>
<Setter Property="FontSize" Value="{Binding Path=FontSize, Source={StaticResource SettingsService}, FallbackValue=12}"/>
</Style>
With your "settings service" defined as a static resource:
<services:SettingsService x:Key="SettingsService"/>
Then in each window make sure the style is set as a DynamicResource:
<Window Style="{DynamicResource MyWindowStyle}" .... >
There is often a lot of misunderstanding around the differences between Static and Dynamic resources, but the basic difference is Static is a "one time" setting whereas Dynamic will update the settings if the resource changes.
Now if you set those properties in your "settings service" they will fire INPC, which will update the Style, which the DynamicResource will pick up on and alter the Window properties accordingly.
Seems like a lot of work, but it gives you some nice flexibility, and all the "heavy lifting" is done purely using Bindings. We use a similar technique on a project I'm working on at the moment so when a user chooses a fill/stroke colour the various tools in the toolbar update to reflect the new values.

Can a WPF window inherit property values from its owner window?

I'd like the child windows in my application to inherit WPF dependency properties from their parent window.
If I set TextOptions.TextRenderingMode="ClearType" on my main window (I'm using WPF 4), that value will apply to all child controls of the window.
How can I make those values also apply to all child windows? (Window instances with Owner set to my main window)
I want to be able to simply change the rendering mode on the main window, and the change should apply to the whole application.
If you want to set it once and leave it, just add a style to your App.xaml inside your <ResourceDictionary> tag:
<ResourceDictionary>
...
<Style TargetType="{x:Type Window}">
<Setter Property="TextOptions.RenderingMode" Value="ClearType">
</Style>
...
</ResourceDictionary>
If you actually want to be able to vary it over time, you can bind to the main window:
<ResourceDictionary>
...
<Style TargetType="{x:Type Window}">
<Setter Property="TextOptions.RenderingMode" Value="{Binding MainWindow.(TextOptions.RenderingMode), Source="{x:Static Application.Current}">
</Style>
...
</ResourceDictionary>
and make sure you set it in the main window explicitly to avoid a self-reference:
<Window TextOptions.RenderingMode="ClearType" ...>
Now any dynamic changes to the TextOptions.RenderingMode of the main window will also affect all other windows. But a simple fixed style is best for most purposes.
There are other solutions for binding it dynamically if you don't care that it be controlled by the main window's value, for example you could use a {DynamicResource ...} in your style or bind to a property of a static object.
Update
Just adding a style for Window in your App.xaml doesn't work if you are using Window subclasses instead of plain Window objects.
To allow the style you define to be applied to all Window subclasses, add the following OverrideMetadata call to your App's constructor (generally in App.xaml.cs) after the InitializeComponent():
public App()
{
InitializeComponent();
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
{
DefaultValue = FindResource(typeof(Window))
});
}
You can use a style resource to give the same property to multiple windows.

Categories