I'm trying to make a wpf style that will allow me to:
1. Base alternate styles off a base style
2. Have the base style be a default that every control uses when no style is applied.
For example, I have code to make style for a button...
<!--Base Button-->
<Style TargetType="Button" x:Key="BaseButton">
<Setter Property="Width" Value="auto"/>
<Setter Property="MaxWidth" Value="100"/>
<Setter Property="Height" Value="auto"/>
<Setter Property="MaxHeight" Value="50"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value=".85"/>
</Trigger>
</Style.Triggers>
</Style>
<!--Apply Base to any Button without a style-->
<Style TargetType="Button" BasedOn="{StaticResource BaseButton}"/>
and here is a style for a specific button...
<Style TargetType="Button" x:Key="DeleteBtn" BasedOn="{StaticResource BaseButton}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="35"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="(some url)" Height="16" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label Content="Delete" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, I would like to be able to base the "DeleteBtn" Style off of the base, but also have the base be the default for every button placed on the screen that doesn't have a specific style set. This currently only works for buttons and no other control. The above example does work, but I can't seem to do the same thing for labels, textboxes etc. Any thoughts or input would be greatly appreciated :)
Here's an example of one that doesn't work..
<!--Base Icon-->
<Style TargetType="Image" x:Key="BaseIcon">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<!--Apply Base to any Icon without a style-->
<Style TargetType="Image" BasedOn="{DynamicResource BaseIcon}"/>
It gives an error: 'DynamicResourceExtension' cannot be set on the 'BasedOn' property of type 'Style'. A 'DynamicResourceExtension' can only be set on a DependencyProperty of a DependencyObject.
Your example only works for Buttons because your "base" style is targeting buttons only.
i.e.
TargetType="Button"
You can try creating a style that targets the parent FrameworkElement instead. Just be warned that not all properties are supported. Some properties are unique to the child control.
It works for me, just tested it.
<Window.Resources>
<Style TargetType="Label" x:Key="BaseLabel">
<Setter Property="Background" Value="Red"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="Label" BasedOn="{StaticResource BaseLabel}"/>
</Window.Resources>
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" Orientation="Horizontal">
<Label Width="100" Content="TestLabel1"/>
<Label Width="100" Content="TestLabel1" Foreground="White"/>
</StackPanel>
</Grid>
Edit: Added derived right alignment for fun.
Related
I have seen some articles that show how to use AlternationIndex with ListBoxes or ListViews, but I had spent a few hours trying to get alternating background colors on the base ItemsControl class and nothing seems to work. All ListBox samples I saw use ListBoxItem as the target type for the style that sets the background based onAlternationIndex - like this one from MSDN:
<Grid>
<Grid.Resources>
<Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property="ListBox.AlternationIndex" Value="1">
<Setter Property="Background" Value="CornflowerBlue"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="ListBox.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Navy"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ListBox AlternationCount="3" ItemsSource="{StaticResource data}"
ItemContainerStyle="{StaticResource alternatingWithTriggers}">
</ListBox>
</Grid>
I want to use the ItemsControl because I do not want the selection functionality and I think restyling a ListBox to hide it might not be the best choice.
This is one of the things I was trying:
<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
<Grid>
<!-- some content here -->
</Grid>
</DataTemplate>
<!-- ... -->
<ItemsControl
ItemsSource="{Binding ObservableCollectionItems}"
AlternationCount="2"
>
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Grid.Background" Value="Red"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Grid.Background" Value="Blue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
The problem I saw was that the visual tree has a list of ContentPresenters that have ItemsControl.AlternationIndex alternate between 0 and 1, but the Grid in each ContentPresenter has ItemsControl.AlternationIndex set to 0.
There is probably something obvious I am missing...
The ItemContainerStyle is applied to the elements generated by the ItemsControl: ContentPresenter. The ContentPresenter will in turn contain whatever you put in your ItemTemplate. In the case of a ListBox, the ItemContainerStyle is applied to the generated ListBoxItem.
The AlternationCount is, based on what you posted, only available on these generated items. You cannot use the ItemContainerStyle to set the Grid's background, because the Grid is unknown to that Style.
The following would be ideal, but unfortunately ContentPresenter has no background property. It would work for a ListBox (with ListBoxItems) however.
<ItemsControl
ItemsSource="{Binding ObservableCollectionItems}"
AlternationCount="2">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Blue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
So you end up writing a style for the grid which binds to the AlternationIndex of your parent ContentPresenter.
<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</DataTemplate>
hm... After about 2 hours of playing around, I finally found the solution that simply works:
<ItemsControl ItemsSource="{Binding}" AlternationCount="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent" x:Name="__PART_GRID"></Grid>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter TargetName="__PART_GRID" Property="Background" Value="Red"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter TargetName="__PART_GRID" Property="Background" Value="Blue"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I hope this answer helps others to save some time.
Or, as I found on another post, and it works great for me...
You can simply use a binding...
{Binding
RelativeSource={RelativeSource Mode=TemplatedParent},
Path=(ItemsControl.AlternationIndex)}
NB: remember to add AlterationCount="100" on your ItemsControl
I don't know how any of the prior answers are legit. I couldn't make any of them work (didn't try Jacobi's though). Anyways, I found the path to enlightenment here: http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, which lead me to adding the following in the xaml.cs code-behind:
public sealed class CustomItemsControl : ItemsControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
}
and this in the xaml itself
<local:CustomItemsControl AlternationCount="2"
ItemsSource="{Binding Cells, Mode=OneWay}">
<local:CustomItemsControl.ItemContainerStyle>
<Style TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="WhiteSmoke"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
</local:CustomItemsControl.ItemContainerStyle>
</local:CustomItemsControl>
This was so damn hard to find a working solution to that I'm actually angry
If you don't want to use the DataTemplate approach, you can create a custom control that uses a ContentControl as the item container, therefore allowing you to specify a background color.
Class:
public class ItemsControlAlternating : ItemsControl
{
static ItemsControlAlternating()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating),
new FrameworkPropertyMetadata(typeof(ItemsControlAlternating)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is ContentControl;
}
}
Resource Dictionary:
<Style TargetType="{x:Type c:ItemsControlAlternating}">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Gray"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
I've got about 300+ buttons that are represented in a grid. When I try to render this, it takes a good 5 seconds to load up all buttons. Is there any alternative? Functionality that already exists such as hover over, mouse enter, left button click etc are all needed... just wondering if there is a way to speed up button rendering.
Buttons are created dynamically in a grid, with an ItemsControl, that contains an ItemsPanelTemplate (that is just a grid definition of width and height), a DataTemplate in ItemsControl.Resources, where the ToggleButton(s) that are created dynamically (300+) are created.
The datatemplate in the ItemsControl.Resources looks like this:
<DataTemplate DataType="{x:Type engine:Weodel}">
<ToggleButton
Tag="{Binding}"
IsChecked="{Binding IsSelected}"
Height="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
Width="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{Binding ElementName=weItemControl,
Path=DataContext.ButtonMarginToUse}"
Padding="2"
Style="{StaticResource WeButton}">
</ToggleButton>
</DataTemplate>
The style of the button in resource dictionary:
<Style TargetType="{x:Type ToggleButton}" x:Key="WeButton">
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Ellipse Fill="{TemplateBinding Background}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextBlock.TextAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have some buttons -in different windows- that have the same content. But if two windows surfaced together,out of the first window's button content disappears.
Buttons Style is :
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
button Code in windows is :
<Button Style="{DynamicResource BSaveBtn}" Template="{DynamicResource FlatGreenBtnHover}" />
problems occurs only with content -not another style properties- .
Seems to work fine for me when I tested it here.
A few things I noticed though that may help. You don't need them to be DynamicResource, they should really be StaticResource unless you plan on modifying them.
I assume you are declaring these in the Windows.Resource section or repeating them on each window?
If so you should centralize those to a ResourceDictionary.
Create a new Resource Dictionary put your style in there like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Then in your App.xaml put the following:
<ResourceDictionary>
<ResourceDictionary Source="MyResources.xaml" />
</ResourceDictionary>
The Image should really be in a dictionary to avoid loading it multiple times. Just add a line in that ResourceDictionary like so:
<BitmapImage UriSource="/login;component/Images/Save.png" x:Key="Save" PresentationOptions:Freeze="True" />
Setting the PresentationOptions:Freeze will also help if the image is never being modified.
Your call to the image would then change to be:
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="{StaticResource Save}"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
Once your resources are centralized in a ResourceDictionary (or multiple) it makes it easy to apply those same styles anywhere in your application and hopefully will help with your issue. If not please give more info on the problem you have such as sample code to make the issue happen please.
An instance of an element can only appear once in the visual tree. You can set the x:Shared attribute of the Style to False in order for a new instance of the StackPanel to get created for each Button to which you apply the style:
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn" x:Shared="False">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
Everywhere I've looked, I've found the standard solution to attach a ToolTip to a control whose Binding has Validation.HasError == true but nowhere shows how you might completely override the ToolTip's template so that you could, for example, still have your own custom theme which overrides the style for all ToolTips but when a control has that specific condition you can specify a template which has a red border, red see-through background and red text, for example.
The standard solution is:
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Does anyone know how to expand this to set the ToolTip background, border and text colour without overriding the base ToolTip control style? Bear in mind I've already specified this to create my own "theme" so I don't want to change it if possible.
Yes, you can do it like this:
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" Style="{StaticResource MyInheritedStyleForValidation}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Where MyInheritedStyleForValidation should probably override your theme style.
Set the DataContext of the ToolTip to the parent control:
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Foreground="White"
Background="Black"
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
Content="{Binding Path=(Validation.Errors)[0].ErrorContent}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
This fix the tooltip content.
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Setter Property="ToolTip" Value="{Binding GeneralTooltip}"/>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationTemplate}"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Style="{StaticResource WarningTooltip}"/>
</Setter.Value>
</Setter>
<Setter Property="Tag" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Style>
The tooltip template from his style:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<!--Display the text-->
<Label Background="Transparent"
BorderThickness="0"
VerticalAlignment="Center"
Grid.Column="1"
Content="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Control}, AncestorLevel=2}}"
BorderBrush="Transparent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
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>