Set ComboBox selected item highlight color - wpf

I need to change the highlight color of a ComboBox's selected item in the popup list. I've found several tutorials explaining how to do this, but all of them either use Blend, which I do not have and cannot obtain, or involve changing the system default colors--which seems like a hack to me.
Can someone point me to the template I need to override, or tell me the property I need to set?

Override the SystemColors.HighlightBrushKey (and SystemColors.HighlightTextBrushKey if you want):
<ComboBox>
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}">Red</SolidColorBrush>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Blue</SolidColorBrush>
</ComboBox.Resources>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
</ComboBox>

I have created a template for Combobox here :
http://wpfstyles.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31388#DownloadId=78720
Thanks,
Vikas

Related

Static resource array binding only works for the first time

I created a custom control which inherits from toolbar.
I would like that the default control template of the toolbar will contain a couple of default buttons.
In order to achieve this, I created a static array to hold the button list:
<x:Array x:Key="toolbarButtons" Type="{x:Type ToggleButton}">
<ToggleButton Content="Bold"
Command="{x:Static ns1:EditingCommands.Bold}"
CommandTarget="{Binding}"
IsChecked="{Binding IsBold, Mode=TwoWay}"/>
<ToggleButton Content="Italic"
Command="{x:Static ns1:EditingCommands.Italic}"
CommandTarget="{Binding}"
IsChecked="{Binding IsItalic, Mode=TwoWay}"/>
</x:Array>
The toolbar control has datacontext which is bounded to a text editor which includes all of the command bindings and the boolean dependency properties (IsBold, IsItalic).
I set the Toolbar ItemSource to use the array like this:
<Setter Property="ItemsSource" Value="{StaticResource toolbarButtons}"/>
Now, when I open a window who hosts the toolbar for the first time on a given run, everything works great.
The problem is, when I close the window, and reopen it, the button bindings stop working (IsCheked property stops being connected to the dependency property).
I used snoop to check the bindings, and it says that the value of IsChecked is local, which means the binding is ignored.
I suspect that the problem is my array is a static resource, so the toolbar uses the same instance from time to time, and this somehow ruins the binding.
My question is how to solve this, or maybe should I use a different approach in order to achieve default buttons for my toolbar?
I think the problem is that when you declare your array in XAML, it's only instantiated once. So, the second toolbar (and on) are trying to use the exact same objects. When it's reused, your bindings are likely being overwritten.
Have you tried adding x:Shared="False" to the array declaration?
<x:Array x:Key="toolbarButtons" x:Shared="False" Type="{x:Type ToggleButton}">

How do the default color, font family and font size for a TextBlock and Label get set in an WPF app?

Edit: I guess the question wasn't stated very clearly. It actually composes of 4 separate ones:
How does a TextBlock get its default color, if the client app doesn't provide any style, either programmatically or through xaml?
How does a Label get its default color?
How does a TextBlock get its default font size and font family, if the client app doesn't provide any style, either programmatically or through xaml?
How does a Label get its default font size and font family?
BTW, the questions are not about how to change or define styles for the color/font size/font family of a TextBlock or a Label, although they are somehow related. I think I already knew the answer for #2, that is a Label gets its color from SystemColors.ControlTextBrushKey and by overriding ConrolTextBrushKey like so:
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Red"/>
You would be able to "globally" change color for Labels. After some research, I guess I also find the answer for #1: A TextBlock inherits the its foreground color from its containing Window, which by default gets its Foreground color from SystemColors.WindowTextBrushKey. By defining a color for the WindowTextBrush like so:
<Window.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.WindowTextBrushKey}"
Color="Yellow"/>
</Window.Resources>
You would be able to change the "foreground" color for the TextBlocks inside the Window.
Question #3 and #4 remain puzzles for me, but I am assuming they have to do with the SystemFonts.
Hope this makes sense. I really like to know the answers as they have been bothering me for a while. Many thanks!
Below is the original post:
If you look into the style for a Label in the theme (for example "aero.normalcolor.xaml") that comes with Windows, you can find
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
Which sets the color for a Label. But there is no where the FontSize property is specified in the style, which I assume has something to do with the SystemFonts. For a TextBlock, it looks even more mysterious as the style for it in "aero.normalcolor.xaml" has only 4 lines:
<Style x:Key="{x:Type TextBlock}"
TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping"
Value="NoWrap"/>
<Setter Property="TextTrimming"
Value="None"/>
</Style>
Where does a Label or a TextBlock get the values for its color and font size/family from, if the app doesn't set any, and where are those hooks in WPF?
Edit:
This is a test drive attempting to set the TextBlock color through SystemColors.ControlTextBrush (assuming that's where a TextBlock gets its default color from, which seems to be false):
<Window x:Class="TestFontColor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<StackPanel.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Red"/>
</StackPanel.Resources>
<Button Content="This is red."/>
<Label Content="This is blue.">
<Label.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Blue"/>
</Label.Resources>
</Label>
<TextBlock Text="TextBlock: This is still black."/>
</StackPanel>
As far as I remember, in most cases classes like TextBlock, TextBox and many others take the text color from the TextElement.Foreground property. The property value is inherited throughout the visual tree, i.e. you may set it on the root element and have most of the text change its color. For example:
<Grid TextElement.Foreground="Red">
<TextBlock Text="test"/>
</Grid>
In fact, the same is true even for labels: the setter in their default style simply sets the TextElement.Foreground to one of the system colors.
However, this is true only for the default state of controls. Altered states, like highlighting, are not inherited, but rather taken from the system colors, as Rachel has written.
UPDATE
The same is true for FontSize and FontFamily. They are properties of the TextElement class that have attached property usage. They inherit their values. Once you set a value on a visual tree item, all its children will get the same value. Unless they override it either by an explicit property assignment, or by style and so on.
Once again, text color font size and font family are governed by the value of TextElement.Foreground, TextElement.FontSize and TextElement.FontFamily attached dependency properties on a specific visual element.
Some controls, like Label explicitly set their Foreground to some brush. It happens so that the brush is one of the SystemColors. But it doesn't have to be true for all controls. Others (TextBlock, TextBox, etc.) don't override the property value and just use some default settings evaluated on startup. The same happens to FontSize and FontFamily. You do not need to set them wherever in order for them to work. That's how WPF works.
Supposedly, the values depend on the system theme. I believe they are evaluated during the app startup. Perhaps they are configurable.
UPDATE 2
Answers to your new questions:
How does a TextBlock get its default color, if the client app doesn't provide any style, either programmatically or through xaml?
It takes it from the inherited value of the TextElement.Foreground attached dependency property. By default it is inherited from the root visual element, which in turn is simply set to the default value of the dependency property (Brushes.Black). See also
How does a Label get its default color?
It takes it from the value of the TextElement.Foreground attached dependency property. Since its default style sets it to the {DynamicResource {x:Static SystemColors.ControlTextBrushKey}, it gets bound to the system color.
How does a TextBlock get its default font size and font family, if the client app doesn't provide any style, either programmatically or through xaml?
The same as for its text color. MSDN says that for the default value of the font size is SystemFonts.MessageFontSize which depends on system settings. Font family is determined in similar way from SystemFonts.MessageFontFamily.
Both these default values are passed to the FrameworkPropertyMetadata constructor upon dependency property registration in the TextElement static constructor.
Going deeper: SystemFonts.MessageFontFamily and SystemFonts.MessageFontSize wrap internal SystemParameters.NonClientMetrics which in turn are retrieved from the WIN32 native SystemParametersInfo http://msdn.microsoft.com/en-us/library/ms724947. Thus the WPF is tightly integrated with all Windows UI stuff like themes, fonts, etc.
How does a Label get its default font size and font family?
The same as for TextBlock. Label derives from ContentControl which in turn derives from Control. Control class adds itself as an owner of the TextElement.FontFamily and TextElement.FontSize properties with the same default values.
See also:
Property Value Inheritance
UPDATE 3
You should understand the main idea: the values are inherited. It means they might be inherited from anywhere, from any control. You can tell exactly which one it is inherited from only for a certain logical tree structure. You change it a bit - and the colors change. Someone sets a property's value explicitly - and all children will inherit the value. Therefore your questions make little practival sense. But they are still interesting from the perspective of undestanding the WPF.
Overriding default values
Although you cannot change the values of the SystemFonts properties (they are read-only), you don't have to. To change the font size and family for the whole window, simply assign the desired values to the TextElement attached properties on the Window:
<Window TextElement.FontSize="20" TextElement.FontFamily="Century Gothic">
..
</Window>
and all controls that do not explicitly override the inheritance will receive the settings. For those that do override - you'll have to override their default styles or even throw them away if they hard-code the values.
The same approach works for TextElement.Foreground (and Background and so on).
The default colors are pulled from the operating system's settings.
You can overwrite them by creating a brush which has the a key that references a SystemColors brush key
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
According to this: http://msdn.microsoft.com/en-us/library/ms788718.aspx
By default, WPF uses the GlobalUserInterface.composite font in your Windows\Fonts directory.
And according to this: http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.95).aspx
A non-negative value that specifies the font size, measured in pixels. The default is 11.
In addition, you can find many of the other default values stored in various places in the MSDN site: http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontstyle(v=VS.95).aspx for the style, which says:
The requested font style, which is a FontStyle that is obtained from one of the FontStyles property values. The default is Normal.

Change ListBoxItem Background color from within ItemTemplate?

I've searched and came up empty, therefore I'm asking.
I found how to change Background and Highlight Background color of ListBoxItem using ItemContainerStyle.
But I'd like to change these 2 colors based on data from within my DataTemplate for Items.
Is that possible?
I think it would be possible to do it with a list, I've already done this kind of thing using Datagrids.
Christian Mosers offers a good and understandable way to do that with DataGrid, you can easily use his datatemplates for ListBoxItems:
http://www.wpftutorial.net/DataGrid.html#rowDetails
EDIT
Have you tried to set a style aiming for ListBoxItems in your listbox's resources?
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Blue" />
</Style>
</ListBox.Resources/>
This should set all your items' bg to Blue
I came up with a solution later on.
The only reasonable way is to define/redefine Listbox Control template.

XAML: Convert a Brush to a Color?

I am creating a custom control with two text colors, ColorA and ColorB. ColorA is wired to the Foreground property of the control, and ColorB is wired to a custom dependency property called ForegroundAlt. Both properties are Brush objects. The control's XAML gets the property values using this markup:
<SolidColorBrush x:Key="BrushA" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
<SolidColorBrush x:Key="BrushB" Color="{Binding Path=ForegroundAlt, RelativeSource={RelativeSource TemplatedParent}}" />
I need to animate sme text between the two colors in the control template, and that's where I am running into problems.
Normally, I would simply create a data binding to each Brush.Color property, like this:
To="{Binding Source={StaticResource BrushB}, Path=Color}"
But that won't work here. It turns out that you can't use bindings on an animation inside a control template.
As a workaround, I would like to create a pair of Color resources to go along with the Brush resources:
<Color x:Key="ColorA" ??? />
<Color x:Key="ColorB" ??? />
Each Color resource should have the color of its corresponding brush. I could then reference the colors as static resources, and avoid having to data bind from within the animation.
So, here are my questions:
-- How would I declare the Color resources?
-- Is there a simpler way to get the job done?
Thanks for your help.
If I've understood this correctly, what you are trying will not work. Even if you define the Colors as resources, you will still have to bind them to the brush resources and you are back to square one!
One solution is to do it in code behind rather than in the template. Since its a custom control you are building its should be pretty straightforward to add it in th code behind without screwing up the design.

Why won't this change the color of my WPF Datagrid headers?

I fill my datagrid in code behind like this:
var customers = from c in _db.Customers
select c;
TheDataGrid.ItemsSource = customers.ToList();
In my XAML below, the DataGrid.RowBackground works but the DataGridHeaderBorder gets the error "The Items listing must be empty before the use of ItemsSource" in the code-behind upon runtime.
This is odd because I'm just trying to change the color of the Datagrid headers and it gets a problem with ItemsSource. If I take the DataGridHeaderBorder line out, it works fine.
So how does one simply change the color of the column headers on a Datagrid?
<toolkit:DataGridHeaderBorder Background="yellow"/>
<toolkit:DataGrid.RowBackground>
<LinearGradientBrush EndPoint="-0.136,-0.163" StartPoint="1.291,1.248">
<GradientStop Color="#FFA8A929" Offset="0.004"/>
<GradientStop Color="#FFF7F7ED" Offset="0.991"/>
</LinearGradientBrush>
</toolkit:DataGrid.RowBackground>
Any time that you put elements within elements, the XAML parser has to decide if the sub-elements are complex property assignments (as you are trying to do), or whether you intend the sub-elements to be the "content" of the parent element. Because your problem "DataGridHeaderBorder" tag does not start with "toolkit:DataGrid", it is assumed that you are trying to set the DataGrid's content property (which happens to be Items) to this value.
I am not in a position to try this, but I would guess you'd need to replace the problem tag with something like:
<toolkit:DataGrid.RowHeaderStyle>
<Style TargetType="{x:Type toolkit:DataGridRowHeader}">
<Setter Property="Background" Value="Yellow" />
</Style>
</toolkit:DataGrid.RowHeaderStyle>

Resources