I have a very specific situation where I need to disable focusable in a List Box, but then the items inside it cannot be selected.
So I added an EventSetter in the item style to send a notification that it has been clicked so I switch to it behind the scenes, but the event isnt firing up.
Any help in making it work is much appreciated!
Heres the full xaml style code:
<Window.Resources>
<Style
x:Key="ListBoxItemStyle"
BasedOn="{StaticResource {x:Type ListBoxItem}}"
TargetType="ListBoxItem">
<Setter Property="Padding" Value="5" />
<Setter Property="IsTabStop" Value="False" />
<!-- Fixes spacebar not working and some other bugs if selecting via mouse -->
<Setter Property="Focusable" Value="False" />
<EventSetter
Event="MouseDown"
Handler="OnThumbnailSelect" />
</Style>
</Window.Resources>
Use the PreviewMouseDown event instead.
Related
I have a simple 1 column ListView and I need to disable the mouse over effect for the GridViewColumnHeader.
I tried grabbing the style from here: http://msdn.microsoft.com/en-us/library/ms788747.aspx
However that gave my header a purple gradient so I guess it was the wrong style. I do notice it has a
<VisualState x:Name="MouseOver">
But I have no idea how to remove that without finding and including the correct GridViewColumnHeader style and then removing it.
I tried the following, but it doesn't do anything (The VisualState overrides?) and wouldn't work anyway as setting the background to null wouldn't be what I want.
<Style x:Key="hcs" TargetType="{x:Type GridViewColumnHeader}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
The problem is, like you said yourself, in MouseOver visual state and its Storyboard. I think it`s better to get rid from redundant functionality than try to override it later. So we basically just need the same style but without that storyboard. For bare minimum we need to have following things (can be found on MSDN via the link you provided):
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Style x:Key="GridViewColumnHeaderGripper"
TargetType="Thumb">
<!-- Full GridViewColumnHeaderGripper style here -->
</Style>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<!-- Standard template but with redundant Storyboard removed -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The last Style doesn`t have a key so it applies to all GridViewColumnHeader on page \ application (depends on where it is defined). Or you can set the key and use it only in specific grids.
That`s bare minimum so for more customizable approach it may be better to copy other parts of default style too.
I have an very, very huge application in WPF with a Ribbon in it. The ribbon contain a bunch of RibbonControls, each binded to a different command. On every control, we put a ToolTip. We overrided these ToolTip templates to use a control of our own, which gives more information. We could call il a superToolTip.
The override of the tooltip templates is working just fine. Now we want to unify the way the tooltips are showing. What I mean is we want the same initialShowDelay, ShowDuration, etc., for every single tooltips in the application (there are tooltips elsewhere than in the ribbon, which use the same home made control that the ones of the ribbon). So, I binded the ToolTipService.InitialShowDelay, ToolTipService.BetweenShowDelay, ToolTipService.ShowDuration properties to global constants in the application.
InitialShowDelay :
The property InitialShowDelay is working just fine for almost every control in the application... The only one not working is RibbonSplitButton, which keep the default value of 400...
BetweenShowDelay :
The property BetweenShowDelay is working just fine when the tooltip is on a ListBoxItem... but not working in the Ribbon nor in a complex control of our own (a Property Grid).
These properties are set in the control on which the tooltip is set, and not on the tooltip themselves.
I honestly have absolutely no idead why it is behaving this way... Anyone has any idea on what could cause this or how to solve it?
If you need more information, do not hesitate to ask, i really am desperate about this.
Thank you very much!
The problem was that the condition for BetweenShowDelay wasn't respected, you need to have a value set for the property "ToolTip", in this case you were using a template, so the value was at null. You can resolve it this way :
<Style x:Key="{x:Type ToolTip}" TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Utils:ToolTipControl DataContext="{Binding ToolTipInfo}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and then place the dummy in the specified button :
<!-- RibbonButton -->
<Style TargetType="{x:Type ribbon:RibbonButton}" BasedOn="{StaticResource RibbonControlStyle}" >
<Style.Triggers>
<DataTrigger Value="true" >
<DataTrigger.Binding>
<Binding Converter="{StaticResource IsBoundConverter}" />
</DataTrigger.Binding>
<Setter Property="Command" Value="{Binding}" />
<Setter Property="ribbon:RibbonControlService.Label" Value="{Binding Name}" />
<Setter Property="ribbon:RibbonControlService.SmallImageSource" Value="{Binding Icon}" />
<Setter Property="ribbon:RibbonControlService.LargeImageSource" Value="{Binding LargeIcon}" />
<Setter Property="Visibility" Value="{Binding Visibility}" />
<Setter Property="ToolTip" Value="dummy"/> <!-- Use dummy value to force tooltip to show and to Bind the tooltip-->
</DataTrigger>
<DataTrigger Value="false" >
<DataTrigger.Binding>
<Binding Converter="{StaticResource IsBoundConverter}" />
</DataTrigger.Binding>
<Setter Property="Background" Value="#FF900000" />
</DataTrigger>
</Style.Triggers>
</Style>
That way the dummy value will be override.
:D
Here is some code showing how I implemented my ToolTips
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
...>
...
<!-- Ribbon Tooltips Style -->
<Style TargetType="ribbon:RibbonToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Utils:ToolTipControl DataContext="{Binding ToolTipInfo}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...
<!-- RibbonControl -->
<Style x:Key="RibbonControlStyle">
<Setter Property="ribbon:RibbonControlService.ToolTipTitle" Value="dummy" /><!-- Use dummy value to force tooltip to show -->
<Setter Property="ToolTipService.InitialShowDelay" Value="{x:Static Utils:ToolTipViewModel.ToolTipInitialDelay}"/>
<Setter Property="ToolTipService.ShowDuration" Value="{x:Static Utils:ToolTipViewModel.ToolTipShowDuration}"/>
<Setter Property="ToolTipService.BetweenShowDelay" Value="{x:Static Utils:ToolTipViewModel.ToolTipBetweenShowDelay}"/>
<!-- This style is used to select the "Editors" tab when opening Editor without a world, and to select the "Home" tab otherwise -->
<Style.Triggers>
<DataTrigger Binding="{Binding IsWorldLoaded, Source={x:Static ViewModels:ViewportSettingsViewModel.Instance}}" Value="false">
<Setter Property="ribbon:Ribbon.SelectedIndex" Value="2"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsWorldLoaded, Source={x:Static ViewModels:ViewportSettingsViewModel.Instance}}" Value="true">
<Setter Property="ribbon:Ribbon.SelectedIndex" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
Also, for the splitbutton problem it was that the tooltipservice werent set for the child of the splitbutton ( the two parts) wich are named PART_HeaderButton and PART_ToggleButton. So even if you create your own style it will be override by the style of the ribbonsplit button ( see this link for the splitbutton.xaml file :
https://wpfcontrolextension.svn.codeplex.com/svn/trunk/Common/RibbonControlsLibrary/v3.5/Themes/Generic.xaml
So to bypass this overriding problem ( because we don't have access to the part directly we have to go via code. Im my case, I overrided the RibbonSplitButton class and the OnLoadTemplate method. That way with getchild we can access the property of the part and change them.
public partial class DuniaRibbonSplitButton : RibbonSplitButton
{
public DuniaRibbonSplitButton()
{
InitializeComponent();
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var HeaderButton = base.GetTemplateChild("PART_HeaderButton");
var ToggleButton = base.GetTemplateChild("PART_ToggleButton");
OverrideAttributes(HeaderButton as Control);
OverrideAttributes(ToggleButton as Control);
}
private void OverrideAttributes(Control control)
{
control.ToolTip = "Dummy";
ToolTipService.SetInitialShowDelay(control, ToolTipViewModel.ToolTipInitialDelay);
ToolTipService.SetShowDuration(control, ToolTipViewModel.ToolTipShowDuration);
ToolTipService.SetBetweenShowDelay(control, ToolTipViewModel.ToolTipBetweenShowDelay);
}
}
How can I make background highlight color dependent on some property of ListViewItem?
This is an issue that people often ask for. Actually, for some reasons, when an item is selected in a ListView or ListBox, the Background color is not the one that is changed. It is a bit more tricky. In fact you need to override the value of the static color resources to which the item template is bound. So to change the higlighting colors of the items you have to do like this:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Orange"/>
</Style.Resources>
</Style>
</ListView.ItemContainerStyle>
</List>
Here is a more developed explanation: Trigger for ListBoxItem
EDIT:
For changing selected background, you will have to override the ListViewItem's Template.
See this... http://msdn.microsoft.com/en-us/library/ms788717(v=vs.90).aspx.
Replace the {StaticResource SelectedBackgroundBrush} with your preferred background brush in the template.
To change backgrounds based on ANY other property that the control template does not rely upon, You can use triggers ...
<ListView ...>
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="SomeListViewItemProperty" Value="Value1">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="SomeListViewItemProperty" Value="Value2">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
<ListView.Resources>
</ListView>
I hope this answers your question.
I use an attached behavior that allows a DoubleClick event to be wired to a command in a view model, as in the binding below:
<ListBox Style="{StaticResource MasterListBoxStyle}"
b:SelectionBehavior.DoubleClickCommand="{Binding EditCommand}"
>
I need multiple list boxes for a presentation, all of which will need a DoubleClick wired to an EditCommand.
Can I push this behavior into my MasterListBoxStyle? How?
Cheers,
Berryl
<Style x:Key="MasterListBoxStyle" TargetType="ListBox">
<Setter Property="ItemsSource" Value="{Binding MasterVm.AllDetailVms}" />
<Setter Property="ItemContainerStyle" Value="{StaticResource MasterListingRowStyle}" />
<Setter Property="IsSynchronizedWithCurrentItem" Value="True" />
<Setter Property="AlternationCount" Value="2" />
</Style>
You should be able to add a simple Setter like so in WPF:
<Setter Property="b:SelectionBehavior.DoubleClickCommand" Value="{Binding EditCommand}" />
Assuming the b xmlns is defined in the XAML file that contains your Style.
This won't work in Silverlight though, since Bindings are not supported in Setters. This is something Microsoft is fixing in Silverlight 5.
In HTML/CSS you can define a style which can be applied to many types of elements, e.g.:
.highlight {
color:red;
}
can be applied to both P and DIV, e.g.:
<p class="highlight">this will be highlighted</p>
<div class="highlight">this will also be highlighted</div>
but in XAML you seem to have to define the TargetType for styles, otherwise you get an error:
<Style x:Key="formRowLabel" TargetType="TextBlock">
is there a way to allow a XAML style to be applied to multiple elements or even to leave it open as in CSS?
The setters in WPF styles are checked during compile time; CSS styles are applied dynamically.
You have to specify a type so that WPF can resolve the properties in the setters to the dependency properties of that type.
You can set the target type to base classes that contain the properties you want and then apply that style to derived classes. For example, you could create a style for Control objects and then apply it to multiple types of controls (Button, TextBox, CheckBox, etc)
<Style x:Key="Highlight" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Red"/>
</Style>
...
<Button Style="{StaticResource Highlight}" Content="Test"/>
<TextBox Style="{StaticResource Highlight}" Text="Test"/>
<CheckBox Style="{StaticResource Highlight}" Content="Test"/>
<!-- Header text style -->
<Style x:Key="headerTextStyle">
<Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
<Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
<Setter Property="Label.FontWeight" Value="Bold"></Setter>
<Setter Property="Label.FontSize" Value="18"></Setter>
<Setter Property="Label.Foreground" Value="#0066cc"></Setter>
</Style>
<!-- Label style -->
<Style x:Key="labelStyle" TargetType="{x:Type Label}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
I think both of these methods of declaring a style might answer your question.
In the first one, there is no TargetType specified, but the property names are prefixed with 'Label'. In the second one, the style is created for Label objects.
Another method to do it is:
<UserControl.Resources>
<Style x:Key="commonStyle" TargetType="Control">
<Setter Property="FontSize" Value="24"/>
</Style>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ListBox"/>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ComboBox"/>
</UserControl.Resources>
I wanted to apply a style to a Textblock and a TextBox but the selected answer didn't work for me because Textblock doesn't inherit from Control, in my case I wanted to affect the Visibility property, so I used FrameworkElement
<Style x:Key="ShowIfRequiredStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowIfRequiredStyle, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
<TextBox Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
This works for the Visibility property because both items inherit from Frameworkelement and the property is defined there. Of course this will not work for properties defined only in Control, you can search the hierarchy tree and try to find a base class, anyway I thought this could help someone since this is a top search result and the selected answer is a little incomplete.
There is an alternative answer to the question. You CAN leave the TargetType parameter off the style altogether which will allow it to apply to various different controls, but only if you prefix the property name with "Control."
<Style x:Key="Highlight">
<Setter Property="Control.Foreground" Value="Red"/>
</Style>
Obviously, this only works for properties of the base control class. If you tried to set ItemsSource say, it would fail because there is no Control.ItemsSource
I got this working
<Style x:Key="HeaderStyleThin" TargetType="{x:Type Border}">
<Setter Property="Background" Value="Black" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background=" Value="Red" />
</Style>
</Style.Resources>
</Style>