Bind to Style Setter from a different Style - c#

how do I go about binding the Foreground Colour of one Style setter to the Fill Colour on another Style Setter, it should be the same object type. This is the code I have got below!
Getting these errors:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'ElementName=MenuItemPath'. BindingExpression:Path=Fill;
DataItem=null; target element is 'TextBlock' (Name=''); target
property is 'Foreground' (type 'Brush')
<Style x:Key="MenuItemName" TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding ElementName=MenuItemPath, Path=Fill}" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<ControlTemplate x:Key="MenuItem" TargetType="RadioButton">
<ControlTemplate.Resources>
<Style TargetType="Path" x:Name="MenuItemPath">
<Setter Property="Fill" Value="#FF22252C" />
<Setter Property="Height" Value="25" />
<Setter Property="Width" Value="25" />
<Setter Property="Stretch" Value="Uniform" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type RadioButton}}, Path=IsChecked}" Value="True">
<Setter Property="Fill" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
</ControlTemplate.Resources>

Personally I would create a separate Resource for storing the brush color, and reference it from both locations.
<SolidColorBrush Color="#FF22252C" x:Key="MenuFillColor" />
<Style x:Key="MenuItemName" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource MenuFillColor}" />
...
</Style>
<ControlTemplate x:Key="MenuItem" TargetType="RadioButton">
<ControlTemplate.Resources>
<Style TargetType="Path" x:Name="MenuItemPath">
<Setter Property="Fill" Value="{StaticResource MenuFillColor}" />
...
</Style>
</ControlTemplate.Resources>
</ControlTemplate>
That said, I've never actually tried binding to another Style's Setter.Value property... it might be possible assuming everything was the same scope. You look like you may have different scopes since you are using <ControlTemplate.Resources> to limit the scope of your MenuItemPath style to just that ControlTemplate. But personally I would not attempt it, and would assume any requirement that needed something like this could also be done some better way :)

It is not possible to access outer property of another style in wpf and that's why you have got binding error. Rather you can declare a color in your resources and from where you can access it.

I was making it more complicated than need be, I just added a DataTrigger which fixed the issue:
<Style x:Key="MenuItemName" TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=MenuItemRadio}" Value="True">
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>

Related

Style BasedOn breaks when x:key is added

I have user control which define custom style for the telerik's control RadTreeViewItem. The problem is that when I don't have x:key there isn't any errors but when I add the x:key property I've got error "The resource "RadTreeViewItemStyle" could not be resolved."
<ResourceDictionary>
<Style x:Key="MySuperGoodStyle" TargetType="telerik:RadTreeViewItem" BasedOn="{StaticResource RadTreeViewItemStyle}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>
</ResourceDictionary>
In runtime there isn't any problems, the style works fine as expected so it looks like design only error.
try to add this before :
<Style TargetType="telerik:RadTreeViewItem" x:Key="RadTreeViewItemStyle">
<Setter Property="FocusVisualStyle" Value="{StaticResource TreeviewFocusVisual}"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1 4 5 4"/>
<Setter Property="MinHeight" Value="24"/>
<Setter Property="IsDropAllowed" Value="True"/>
<Setter Property="IsEnabled" Value="True"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="telerik:DragDropManager.TouchDragTrigger" Value="TapAndHold"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local"/>
<Setter Property="Template" Value="{StaticResource TreeViewItemDefaultTemplate}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<telerik:TreeViewPanel VerticalAlignment="Bottom"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
and be sure to have in your header :
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"

Adding one WPF style property kills all other style properties

I've a style for my WPF buttons, defined in the main window:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="Auto" />
<Setter Property="Height" Value="Auto" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="#FFFFFF" />
<Setter Property="Background" Value="#3fa9f5" />
...
</Style>
</Window.Resources>
In an UserControl, I want to set the content and the background depending on a binding:
<Button.Style>
<Style TargetType="Button">
<Setter Property="Content" Value="Text123" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myControl, Path=IsHidden}"
Value="true">
<Setter Property="Content" Value="TextABC" />
<Setter Property="Background" Value="#ff1d25" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
The problem: The button in the UserControl looses all other properties it gets from the main window style (color, width, margins, ...).
I tried to let the UserControl button's style know the parent style via
BasedOn="{StaticResource {x:Type Button}}"
but with no result.

WPF :Material Design + dragablz tabItem header style

I am working in WPF with the MaterialDesign Toolkit and Dragablz.
I encountered a problem while trying to style a TabablzControl.
I already have style for the windows default TabControl and TabItem header, as shown in the picture:
http://i.imgur.com/2anl5rl.png
But when I change the default tabControl to TabablzControl, it turns into this:
http://i.imgur.com/bhaaMVy.png
Here are the window.resources:
<Style x:Key="mdTabControl" TargetType="TabControl">
<Setter Property="TextElement.Foreground" Value="{DynamicResource MaterialDesignBody}"/>
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}"></Setter>
</Style>
<Style x:Key="mdTabHeader" TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}"></Setter>
<Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Margin="1,0,1,0" CornerRadius="3 3 0 0">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header" Margin="10,2,10,2"
RecognizesAccessKey="True">
</ContentPresenter>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource SecondaryAccentBrush}" />
<Setter Property="Foreground" Value="{StaticResource SecondaryAccentForegroundBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Panel.ZIndex" Value="100" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource PrimaryHueMidBrush}" />
<Setter Property="Foreground" Value="{StaticResource PrimaryHueMidForegroundBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource PrimaryHueDarkBrush}" />
<Setter Property="Foreground" Value="{StaticResource PrimaryHueDarkForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The error appears when I change the mdTabControl style targetType to:
TargetType="dbz:TabablzControl"
I want to keep the style I set to the TabControl, but with the added functionality of the TabablzControl
Any help will be appreciated
First thing to note, which is a general WPF characteristic, you are not using style inheritance correctly.
As you are using Material Design with Dragablz, if you are restyling the tab control itself, you must inherit from the Material Design style in the Dragablz assembly using BasedOn:
<Style x:Key="mdTabControl" TargetType="TabControl" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}">
<Setter Property="TextElement.Foreground" Value="{DynamicResource MaterialDesignBody}"/>
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}"></Setter>
</Style>
Again, with the tab header itself, you need to inherit from the relevant style:
<Style x:Key="mdTabHeader" TargetType="{x:Type TabItem}" BasedOn="{StaticResource MaterialDesignDragableTabItemStyle}">
. . .
</Style>
Note, that (depending you your App.xaml setup) you probably need to make sure the correct resource dictionary is included in the same XAML file. For example a more complete XAML might be:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="NormalTabItemStyle" TargetType="{x:Type dragablz:DragablzItem}" BasedOn="{StaticResource MaterialDesignDragableTabItemStyle}">
<Setter Property="Width" Value="280" />
<Setter Property="Padding" Value="1" />
</Style>
. . .
</ResourceDictionary>
</Window.Resources>
Finally, as you are changing the TabItem style, you either need to the TabablzCOntrol style the correct style, or you could use it where you actually declare the TabablzControl itself:
<dragablz:TabablzControl ItemContainerStyle="{StaticResource mdTabHeader}" />
A good example of all this in action is in the SidePanels project in the demo solution at: https://github.com/ButchersBoy/DragablzSamplez
<Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}"/>

MenuItem Style override single role style

is there any way to override a single role style of MenuItem? I know the way to override the IsHighlighted color of MenuItem is to override the ContentTemplate. What i want is to override the ContentTemplate for Role "SubmenuItem"
<Style x:Key="ActionMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template" Value="{StaticResource SubmenuItemTemplateKey2}" />
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="Role" Value="TopLevelHeader">
<Setter Property="Padding" Value="7,2,8,3" />
<Setter Property="Template" Value="???" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<Trigger Property="Role" Value="TopLevelItem">
<Setter Property="Padding" Value="7,2,8,3" />
<Setter Property="Template" Value="???" />
</Trigger>
<Trigger Property="Role" Value="SubmenuHeader">
<Setter Property="Padding" Value="2,3,2,3" />
<Setter Property="Template" Value="???" />
</Trigger>
<Trigger Property="Role" Value="SubmenuItem">
<Setter Property="Padding" Value="2,3,2,3" />
</Trigger>
</Style.Triggers>
</Style>
The {StaticResource SubmenuItemTemplateKey2} is my override ContentTemplate. For the other roles i want use the default templates of MenuItem. Is there any way to do it?
Best regards
Lutze
You're trying to override all the menu items and next trying to override it again (to set it back to default style). In this case you just need to override the menu item with role of SubmenuItem, so the code can be just like this:
<Style x:Key="ActionMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="HorizontalContentAlignment"
Value="{Binding Path=HorizontalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment"
Value="{Binding Path=VerticalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="Role" Value="TopLevelHeader">
<Setter Property="Padding" Value="7,2,8,3" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<Trigger Property="Role" Value="TopLevelItem">
<Setter Property="Padding" Value="7,2,8,3" />
</Trigger>
<Trigger Property="Role" Value="SubmenuHeader">
<Setter Property="Padding" Value="2,3,2,3" />
</Trigger>
<Trigger Property="Role" Value="SubmenuItem">
<Setter Property="Padding" Value="2,3,2,3"/>
<!-- override here -->
<Setter Property="Template"
Value="{StaticResource SubmenuItemTemplateKey2}"/>
</Trigger>
</Style.Triggers>
</Style>
Otherwise (following your original approach), we may need some dummy MenuItem element which has the default style. Then we can Bind the Template of whatever items to the Template of that dummy element to restore their default style.

Binding Failure on ToolBar Dragging

I have have a ToolBar which I am styling using the code shown below. I have come across three problems with the my ToolBar styling:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org">
<Style x:Key="ToolBarToggleButton" TargetType="{x:Type ToggleButton}"
BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Setter Property="Icon" Value="{Binding Icon}"/>
<Setter Property="ToolTip" Value="{Binding FullToolTip}" />
<Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
<Setter Property="IsChecked" Value="{Binding IsChecked}" />
<Setter Property="cal:Action.Target" Value="{Binding}" />
<Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
</Style>
...
First:
The tool bar images are currently getting used as a single static instance. Even with the property x:Shared="False" moving the ToolBar one over another will cause a rendering failure.
Solution:
In the ToolTip Styles.xaml, include the image source as a ContentTemplate
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org">
<Style x:Key="ToolBarToggleButton" TargetType="{x:Type ToggleButton}"
BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image x:Shared="false" Source="{Binding Icon}">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="Stretch" Value="Fill" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="{Binding FullToolTip}" />
<Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
<Setter Property="IsChecked" Value="{Binding IsChecked}" />
<Setter Property="cal:Action.Target" Value="{Binding}" />
<Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
</Style>
<Style x:Key="ToolBarButton" TargetType="{x:Type Button}"
BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image x:Shared="false" Source="{Binding Icon}">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="Stretch" Value="Fill" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="{Binding FullToolTip}" />
<Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
<Setter Property="cal:Action.Target" Value="{Binding}" />
<Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
</Style>
</ResourceDictionary>
Now we have:
No other changes required.
Second:
The same dragging procedure the ToolTip and ToolTipService bindings also get corrupted - at this stage I am not sure of the underlying reason. The quick solution is to do what I have done with the image above and add the ToolTip to the Image. However, this causes the ToolTip only to show when over the Image and not when hovering over the very edge of the button.
Partial Solution:
Add the ToolTip to the Image. However, this is not ideal as then the tool tips do not show when on the very edge of the button.
Third:
When the drag operation shown above occurs, this also breaks the Caliburn property bindings
<Setter Property="cal:Action.Target" Value="{Binding}" />
<Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
Questions: (Second and Third Problem)
How to fix the problem with the ToolTip rendering?
How to fix the problem with the Caliburn property binding?
Thanks for your time.
Solution:
"I've finally fixed this. As near as I can tell, when you initiate a drag on a toolbar, any toolbar items on other toolbars which are covered by the toolbar you're dragging get removed from their current position in the visual tree, and then (presumably) added back when they're made visible again.
When they're removed from the visual tree (again, that's what I think is happening), they also lose access to the ToolBarToggleButton and ToolBarButton styles, because those are defined in the Styles.xaml resource dictionary which is added in ToolBarsView.xaml.
However, if you define those same styles globally, then it works - presumably, even though they're no longer children of ToolBarsView, they still have access to the global resources.
So... I've added a new property, IModule.GlobalResourceDictionaries, which allows each module to declare any resource dictionaries that should be added at the global scope. The ToolBars module makes use of this."
https://github.com/tgjones/gemini/issues/67#issuecomment-60040008
Try to re-assign the tooltips as a style trigger for the mouse over event such as:
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="{Binding FullToolTip}" />
<Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="ToolTip" Value="{Binding FullToolTip}" />
<Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>

Categories

Resources