How to set dynamic and static resource at same time in Xaml? - wpf

I want to assign both static and dynamic styles to a control at same time.
Something like this
<Button
Style="{StaticResource homeScreenBackButton}"
Style="{DynamicResource MahApps.Metro.Styles.MetroCircleButtonStyle}">
<Button.Content>
<Image Source="wwwroot/images/homescreen-back2.png" />
</Button.Content>
</Button>
I could easily achieve this
<Button
Width="38"
Height="38"
HorizontalAlignment="Center"
Cursor="Hand"
Style="{DynamicResource MahApps.Metro.Styles.MetroCircleButtonStyle}">
<Button.Content>
<Image Source="wwwroot/images/homescreen-back2.png" />
</Button.Content>
</Button>
But I don't want to hardcode the styles in this way.

Obviously you cannot set a single property like Style to two different values simultaneously. You can base a Style on another one though:
<Image x:Key="img" x:Shared="false" Source="wwwroot/images/homescreen-back2.png" />
<Style x:Key="homeScreenBackButton" TargetType="Button" BasedOn="{StaticResource MahApps.Metro.Styles.MetroCircleButtonStyle}">
<Setter Property="Content" Value="{StaticResource img}" />
</Style>
Usage:
<Button Style="{StaticResource homeScreenBackButton}" />

Related

Override or add some style properties in WPF

I am porting a Bootstrap theme to WPF and faced a problem: I can't change some properties using additional style for StackPanel. I have ResourceDictionary containing BtnBase base style and BtnPrimary, BtnSecondary etc. All of them were inherited from BtnBase and contain only color properties. BtnBase does not contain any margin rule. When I try to add margin rule for a current StackPanel, there is no effect. I read about styles and knew that more than one style can't be applied, styles in ResourceDictionary have higher priority and I should use BasedOn. But I need to copy and paste my style in the StackPanel and replace BasedOn for each button variant. Is there a way to bypass it and add margin property for all styles?
code:
<StackPanel Orientation="Horizontal" Height="32">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BtnBase}>
<Setter Property="Margin" Value="0,0,10,0"/>
</Style>
</StackPanel.Resources>
<Button Style="{DynamicResource BtnPrimary}" Content="Primary" />
<Button Style="{DynamicResource BtnSecondary}" Content="Secondary" />
<Button Style="{DynamicResource BtnSuccess}" Content="Success" />
<Button Style="{DynamicResource BtnInfo}" Content="Info" />
<Button Style="{DynamicResource BtnWarning}" Content="Warning" />
<Button Style="{DynamicResource BtnDanger}" Content="Danger" />
<Button Style="{DynamicResource BtnLight}" Content="Light" />
<Button Style="{DynamicResource BtnDark}" Content="Dark" />
</StackPanel>
You can treat all buttons as Items in ListBox.
ListBox will create a ListBoxItem for each Button, and you can add Margin to those ListBoxItems, using ItemContainerStyle. That doesn't modify Buttons styles, but creates same effect.
In ItemContainerStyle I also change ListBoxItem template to undo hover, selection colors, etc, which can change appearance - just plain ContentPresenter is left.
ItemsPanel by default is vertical StackPanel, but I changed ItemsPanel and layout to horizontal StackPanel.
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Height="32"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<Button Style="{DynamicResource BtnPrimary}" Content="Primary" />
<Button Style="{DynamicResource BtnSecondary}" Content="Secondary" />
<Button Style="{DynamicResource BtnSuccess}" Content="Success" />
<Button Style="{DynamicResource BtnInfo}" Content="Info" />
<Button Style="{DynamicResource BtnWarning}" Content="Warning" />
<Button Style="{DynamicResource BtnDanger}" Content="Danger" />
<Button Style="{DynamicResource BtnLight}" Content="Light" />
<Button Style="{DynamicResource BtnDark}" Content="Dark" />
</ListBox>

WPF Button style won't apply to second button

I have two buttons that use a static common style:
<Button x:Name="BtnCreate" Height="22" Width="150" Style="{StaticResource Style.Button.Trash}"/>
<Button x:Name="aefae" Height="22" Width="150" Style="{StaticResource Style.Button.Trash}"/>
The style is very basic:
<Style TargetType="Button" x:Key="Style.Button.Trash"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal" >
<Image Source="{StaticResource Image.Trash}" Width="22" Height="22"/>
<Label Content="Save" VerticalAlignment="Center" Height="26" />
</StackPanel>
</Setter.Value>
</Setter>
</Style>
The style applies to the first button and display both the image an the text however the second button does not display anything except a grey button.
Why does the second button not use the static style?
As you're trying to add the same Content to two Buttons, elements (present in Style) cannot be added to two different Logical Parents. To avoid this, you can set x:Shared="False" to your style.

I want to be able to specify a style for a tooltip on some MenuItems, how do I do that?

I want to specify a template for the tooltips of some MenuItem controls on my views. I've put the following into a resource dictionary:
<Style TargetType="{x:Type ToolTip}" x:Key="MenuItemToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<HeaderedContentControl>
<HeaderedContentControl.Header>
<TextBlock FontSize="20" Background="#2288C6" Foreground="White" Padding="3">Click to report a bug</TextBlock>
</HeaderedContentControl.Header>
<HeaderedContentControl.Content>
<StackPanel>
<TextBlock Margin="0,5">Please do <Run FontWeight="Bold">not</Run> change the send To email address.</TextBlock>
<TextBlock>Also, leave the <Run FontStyle="Italic">BUG: BOTS</Run> in the subject line alone.</TextBlock>
<!-- more text blocks, but removed for brevity -->
</StackPanel>
</HeaderedContentControl.Content>
</HeaderedContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
Then in one of the views I've tried using it like so:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.Style>
<Style Resources="{StaticResource MenuItemToolTip}" />
</MenuItem.Style>
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
At first I tried this, but this was just as bad:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}" ToolTip="{StaticResource MenuItemToolTip}">
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
So, how do I get my style into a resource dictionary so that I can use it on some MenuItems, but not all?
The problem with your first approach is that Style.Resources accepts a ResourceDictionary but you are setting it to a Style
Your second approach does not work because you are applying a Style object to the ToolTip property. So an implicit ToolTip is created which tries to Render your style. But since Style is not a UIElement,
what you get is a TextBlock with it's Text property set to whatever text is returned from Style.ToString, which is the name of the Style class by default.
The simplest way here would be to explicitly create a ToolTip for each of your MenuItems and set the styles there. For example:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style={StaticResource MenuItemToolTip} Content="Your Tooltip text" />
</MenuItem.ToolTip>
</MenuItem>
Another option would be to add an implicit style to the Resources property of the MenuItem so that it will be applied
to all ToolTips inside the visual tree of the MenuItem.
<MenuItem ToolTip="Hello">
<MenuItem.Resources>
<Style TargetType="{x:Type ToolTip}">
.. setters
</Style>
</MenuItem.Resources>
</MenuItem>
I prefer the former because it's the simplest.
You can specify the tooltip style directly by using the tooltip control like this:
<MenuItem Background="{x:Null}"
Foreground="#FF706C6C"
Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style="{StaticResource MenuItemToolTip}" />
</MenuItem.ToolTip>
...
</MenuItem>

Make form semi transparent to see form's background image

I'm using WPF (c#) form with background image (background imagebrush).
I want to make all the UI elements(button , title, textbox)... become semi-transparent so that they don't cover the image completely,
but the background image still being visible (not semi-transparent)
I would like a way we can do it without having to set all the opaque value of UI elements.
Maybe this could help
<Window.Resources>
<Style x:Key="transparentControls" TargetType="Button">
<Setter Property="Opacity" Value="0.1"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="MyImage.jpg"/>
</Grid.Background>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" VerticalAlignment="Top" Content="Hey"/>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" Content="There"/>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" VerticalAlignment="Bottom" Content="Click Me"/>
</Grid>
Just try to put all your UI elements in a Canvas or Grid and set the Opacity of that parent element.
Like that:
<Canvas Opacity="1">
<Button Width="100" Height="100"></Button>
</Canvas>
I hope this was what you meant.

Setting Button's Content to <Image> via Styles

Can't get this to work:
<UserControl>
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="TestStyle" TargetType="{x:Type Button}">
<Setter Property="Button.Content">
<Setter.Value>
<Image Source="D:\Temp\dictionary16.png"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<Button Style="{StaticResource TestStyle}"/>
<Button Style="{StaticResource TestStyle}"/>
</StackPanel>
</UserControl>
This code throws the following exception (pointing to the second button):
Specified element is already the logical child of another element. Disconnect it first.
The style creates one instance of the Image, you cannot use it in two places like this. You can create the image as a separate resource with x:Shared= false and reference it in the style then a new one will be created in every place the style is used.
e.g.
<UserControl>
<UserControl.Resources>
<Image x:Key="img" x:Shared="false" Source="D:\Temp\dictionary16.png" />
<Style x:Key="TestStyle" TargetType="{x:Type Button}">
<Setter Property="Content" Value="{StaticResource img}" />
</Style>
</UserControl.Resources>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<Button Style="{StaticResource TestStyle}" />
<Button Style="{StaticResource TestStyle}" />
</StackPanel>
</UserControl>
Already yesterday i found a user with a similar problem: WPF - Change a button's content in a style?
This post got me to this soloution (couldn't post it because of 8 hour limit of stackoverflow -.-)
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{mcWPF:LangRes imgSettings16, Bitmap}" Height="14"/>
</DataTemplate>
</Setter.Value>
</Setter>
Don't know weather this is more clean/dirty/better than H.B.'s soloution

Resources