How do buttons style optimize in XAML code? - wpf

<Style x:Key="ToolBarButton" TargetType="{x:Type Button}">
<Setter Property="Control.Background" Value="#00000000"/>
<Setter Property="Control.Width" Value="25"/>
<Setter Property="Control.Height" Value="25"/>
</Style>
...
<Grid HorizontalAlignment="Left">
<Button Style="{StaticResource ToolBarButton}"/>
<Button Style="{StaticResource ToolBarButton}"/>
<Button Style="{StaticResource ToolBarButton}"/>
<Button Style="{StaticResource ToolBarButton}"/>
<Button Style="{StaticResource ToolBarButton}"/>
<Button Style="{StaticResource ToolBarButton}"/>
</Grid>
I wanna optimize my XAML code. I don't wanna assign a style to each button, but I wish every button to have my style.
Is it possible to do something like this? Only working ... :)
<Grid x:Name="gToolBar" Grid.Row="1" HorizontalAlignment="Left" Style="{StaticResource ToolBarButton}">
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
</Grid>
I don't use TargetType only, because I have other buttons with different styles.
I think it available, but i don't know how.
Thanks...

As i already said everything that is to be done in the comment, but for further clarification:
I wanna optimize my XAML code. I don't wanna assign a style to each button, but I wish every button to have my style.
Move the Style part to <Application.Resources> in App.xaml file, Like shown below:
<Application.Resources>
<Style TargetType="Button" >
<Setter Property="Control.Background" Value="#00000000"/>
<Setter Property="Control.Width" Value="25"/>
<Setter Property="Control.Height" Value="25"/>
</Style>
</Application.Resources>
Note: I've removed the x:Key part. Now this will apply to all the button's that is in the application.
I don't use TargetType only, because I have other buttons with different styles. I think it available, but i don't know how.
For this you would have to make a custom button as a UserControl, thus making them completely different from a usual Button. Apply styling to them in their own UserControl.Resources. Thus styling mentioned in App.Resources won't affect these custom made UserControls

You can create a default style for buttons within the grid:
<Window ...>
<Window.Resources>
<Style x:Key="ToolBarButton" TargetType="{x:Type Button}">
<Setter Property="Control.Background" Value="#00000000"/>
<Setter Property="Control.Width" Value="25"/>
<Setter Property="Control.Height" Value="25"/>
</Style>
</Window.Resources>
<Grid HorizontalAlignment="Left">
<Grid.Resources>
<Style x:Key="{x:Type Button}" BasedOn="{StaticResource ToolBarButton}" TargetType="{x:Type Button}"></Style>
</Grid.Resources>
<Button />
<Button />
<Button />
<Button />
<Button />
<Button />
</Grid>
</Window>
If you create a resource that uses a control type as key within a container, the style will get applied to all controls of the type within the container. If you want to define the original style somewhere else (for example because you use it in many place) you can base the local style off the global style.

You should use application resources to do that. add this code to there(app.xaml):
<Application.Resources>
<Style TargetType="Button" >
<Setter Property="Control.Background" Value="#00000000"/>
<Setter Property="Control.Width" Value="25"/>
<Setter Property="Control.Height" Value="25"/>
</Style>
</Application.Resources>
UPDATE
Or if you want this style apply just some part of your application such some special 'Grid' or special Window ..., just put it inside Resource of that element like this:
<Grid>
<Grid.Resources>
<Style TargetType="Button" >
<Setter Property="Control.Background" Value="#00000000"/>
<Setter Property="Control.Width" Value="25"/>
<Setter Property="Control.Height" Value="25"/>
</Style>
</Grid.Resources>
... inside code, and your buttons which we eant to apply style for them.
</Grid>

Related

How to make an exception for Application.Resources style in a specific Grid.Resources

I am doing small WPF app for my own using Visual Studio, C#, .NET Standard and WPF in this specific project.
I have defined style for all TextBlocks and TextBoxes in Applications.Resources like below.
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="10"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10"/>
</Style>
</Application.Resources>
Then in main window I have a grid which contains some buttons.
<Grid>
<Grid.Resources>
<Style TargetType="Button">
<Setter Property="FontSize" Value="50" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="50"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Content="DASHBOARD" Command="local:CustomCommands.ShowDashboard"/>
</Grid>
I would like to set for the textblocks/textboxes in this specific buttons a wider font.
I tried for many different syntax but could not manage it. I tried also do define x:Key for this style in Grid.Resources and use it in this specific Button control. This wasn't work either.
Can anyone let me know which way should I let know my application that text in this buttons would have bigger font size?
The TextBlock created for string contents by the ContentPresenter inside the Button template doesn't apply the locally-defined resources, i.e. those in your Grid.
The easiest way to solve your problem would be to explicitly define a TextBlock as the Button's content.
<Grid>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="50"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Command="local:CustomCommands.ShowDashboard">
<TextBlock Text="DASHBOARD" />
</Button>
</Grid>

Is Style Inheritence with nested User Controls Possible In WPF?

I'm pretty sure it's not possible to use BasedOn with regards to a Style declaration in a nested UserControl, and be able to reference a Style declaration made in a parent UserControl - can anyone confirm this?
I've tried BasedOn="{StaticResource}" and BasedOn="{DynamicResource}" and neither work.
(Pseudo code sample below)
<Window>
<UserControl>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</StackPanel.Resources>
<UserControl2> <!--this will reside in a different .xaml file...-->
<Button Content="Hello World">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="????">
<!--is this possible to inherit the red background?-->
<Setter Property="Padding" Value="10" />
</Style>
</Button.Style>
</Button>
</UserControl2>
</StackPanel>
</UserControl

WPF toolbar's style not working

I'm using a resource dictionary in my wpf proyect.
The dictionary has these 2 styles:
<Style x:Key="MyMenu" TargetType="Menu">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style x:Key="MyToolbar" TargetType="ToolBar">
<Setter Property="Background" Value="Black"/>
</Style>
And in my XAML file, I use these 2 styles as it follows:
For the menu:
<Menu Name="menuMainBar" Style="{DynamicResource MyMenu}" IsMainMenu="True" VerticalAlignment="Top" Margin="0,10,0,0">
<MenuItem ...
</Menu>
For the toolbar:
<ToolBarTray Name="toolBarTrayRigth_wargames" Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50">
<ToolBar Name="toolBarRigth_wargames" Style="{StaticResource MyToolbar}" BorderThickness="0,0,1,0">
<Button ...
</ToolBar>
</ToolBarTray>
This is the result:
As you can notice, the menu takes the style correctly, but the toolbar isn't affected by the style at all.
I tried removing all the style elements from the toolbartray tag, as it follows:
<ToolBarTray Name="toolBarTrayRigth_wargames">
...
</ToolBarTray>
And now the toolbar works, but as you can see, now the toolbarTray is not how I want it to be (I want a vertical toolbar, not a horizontal toolbar):
I also tried setting the background of the ToolBar directly in the xaml file:
<ToolBarTray Name="toolBarTrayRigth_wargames" Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50">
<ToolBar Name="toolBarRigth_wargames" BorderThickness="0,0,1,0" Background="Black">
<Button ...
</ToolBar>
</ToolBarTray>
...and it works:
But I don't want to do that, I want to use a resource dictionary for my toolbar's style.
any ideas on how to achieve that?
I found, bizarrely, that if I set the Orientation of the parent ToolBarTray to Horizontal, that your ToolBar style was able to set the background on the ToolBar.
I also found that with the ToolBarTray orientation still being Vertical, this worked to set the ToolBar's background:
<Style x:Key="MyToolbar" TargetType="ToolBar">
<Style.Triggers>
<!--
This is intentional. A conventional setter was found not to set the background
when the parent ToolBarTray's Orientation was Vertical.
-->
<DataTrigger Binding="{Binding Source={x:Null}}" Value="{x:Null}">
<Setter Property="Background" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
I find this very strange.
as #EdPlunkett found, its a strange Setter in the default template in the Trigger for Vertical Orientation:
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Margin" TargetName="Grid" Value="1,3,1,1"/>
<Setter Property="Style" TargetName="OverflowButton">
<Setter.Value>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="#FFEEF5FD"/>
you can edit the template (in Document Outline panel, right click on the ToolBar element > Edit Template > Edit a Copy...), and remove this Setter.

Making all images be of the same size and margin

I noticed that I've got a few images in a stack panel and every such has exactly the same size, margin, alignment etc. set to it. I don't want to create a global resource for style. Is it possible to have a local style declared in this specific panel and only for the images (TargetType is enough in this case)?
I'd like something along this solution with the exception that I don't use the global style resource.
<StackPanel.Resources>
<Style TargetType="Image">
<Setter Property="Width" Value="24" />
...
</Style>
</StackPanel.Resources>
<Image Source="{StaticResource Poof}"
VerticalAlignment="Top"
...
Margin="20,20,20,0" />
Just put the style in the resources for the panel, and it will apply to all items of that type, inside the panel.
For example:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Width" Value="200" />
</Style>
</StackPanel.Resources>
<TextBox Margin="20" />
<TextBox Margin="20" />
<TextBox Margin="20" />
<TextBox Margin="20" />
</StackPanel>
Results in all the text boxes having a width of 200 units.
Unless, you override the style with a setting on the individual items. Perhaps you are doing that?
Try add style inside resources.
<Page.Resources>
<Style TargetType="Image">
<Setter Property="Width" Value="80"/>
<Setter Property="Height" Value="80"/>
</Style>
</Page.Resources>

Extend UserControl.Resources

I want to provide a simple default style for a UserControl, but still be able to extend or override the style when using the control. Below is a sample scenario with a simple UserControl and a Window containing the control. The intention is for the style for the Button provided in the Window to override the default style defined in the UserControl.
UserControl
<UserControl x:Class="Sample.TestControl" ... >
<UserControl.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="2" />
<Setter Property="Foreground" Value="Orange" />
</Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Background" Value="Black" />
</Style>
</UserControl.Resources>
<StackPanel>
<Button Content="Press Me" />
<Button Content="Touch Me" />
<Button Content="Tap Me" />
</StackPanel>
</UserControl>
Window
<Window x:Class="Sample.MainWindow" ... >
<Grid>
<local:TestControl>
<local:TestControl.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="2" />
<Setter Property="Foreground" Value="Green" />
</Style>
</local:TestControl.Resources>
</local:TestControl>
</Grid>
</Window>
Problem
The above code will result in:
Exception: Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.
InnerException: Item has already been added.
The above code is trying to submit two styles with the same key into the same ResourceDictionary, so obviously it wasn't going to work. My guess that I am not going to be able to provide a default style for the buttons...
Insufficient Workaround: Override default ResourceDictionary
<Window x:Class="Sample.MainWindow" ... >
<Grid>
<local:TestControl>
<local:TestControl.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="2" />
<Setter Property="Foreground" Value="Green" />
</Style>
</ResourceDictionary>
</local:TestControl.Resources>
</local:TestControl>
</Grid>
</Window>
By putting the custom Button style in a ResouceDictionary, I can override the default one. However, its not just overriding the Button style, its overriding all of the resources. So, the StackPanel will no longer have a black background. (obviously I could add that to the overriding style as well, but thats not practical on a bigger scale.)

Resources