WPF: Change FontSize of ComboBox without knowing items - wpf

I want to set the FontSize for some ComboBoxes in wpf. But the only solution I found, is to set the FontSize of the particular ComboBoxItems. But the items are dynamically added (so I could listen on ItemsChanged and set the style each time, but that is very ugly).
Is there a way to set the FontSize for all items of a ComboBox generally?
EDIT1: The ComboBoxes themselves are also dynamically added in code.
EDIT2: Following your answers it must be something like this:
<Style TargetType="ComboBox" x:Key="MyComboBox"">
<Setter Property="ItemContainerStyle" Value="{DynamicResource MyComboItemStyle}"/>
</Style>
<Style x:Key="MyComboItemStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="FontSize" Value="14"/>
</Style>
But it also has no effect!
EDIT3: Here's how I add the Items:
string[] strEnums = //Some dynamic magic;
foreach (string str in strEnums)
{
(input as ComboBox).Items.Add(strEnum);
}
EDIT4: And here's the initialization of the combobox:
input = new ComboBox();
input.SetResourceReference(ComboBox.StyleProperty, "MyComboBox");
That's all!

1.If you want to set the FontSize for the entire ComboBox, you can set the FontSize property of the ComboBox itself:
<ComboBox FontSize="18" ...>
...
</ComboBox>
2.If you want to change the FontSize only on items or change the font size based on some criteria, you should specify `ItemContainerStyle':
<ComboBox ...>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="FontSize" Value="18"/>
</Style>
</ComboBox.ItemContainerStyle>
...
</ComboBox>

You can define the way how all the items get rendered with defining the ItemTemplate of the ComboBox. In there you bind to the properties of the bound Items.
Example:
<ComboBox ItemsSource="{Binding whateverbinding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Content}" FontSize="12" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Related

How to Bind ListViewItem's ToolTip to a ToolTip of TextBlock inside its ContentTemplate

I would like to bind my ListViewItem's ToolTip to its ContentTemplate's TextBlock's ToolTip.
I tried the following but it didnt work:
<ListView ItemsSource="{Binding DoestMatter}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding ElementName=Title, Path=ToolTip}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Title" Text="{Binding Title}" ToolTip="Test"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The ToolTip's value is dynamically generated, here I just showed it as static string but actually it isn't, and that's why I need to bind it to the TextBlock's ToolTip.
How can I make it work?
Your code works just fine as it is... well, I had to change some Bindings to get it to work, but the main XAML is fine:
<ListView ItemsSource="{Binding Tests}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding ToolTip, ElementName=Title}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Title" Text="{Binding Name}"
ToolTip="Test" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
However, one thing that I did notice was that it only works if you put your cursor directly over the TextBlock and that was not stretching across the width of the ListViewItem. To fix that, just set the HorizontalContentAlignment property to Stretch:
<ListView ItemsSource="{Binding Tests}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding ToolTip, ElementName=Title}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Title" Text="{Binding Name}"
ToolTip="Test" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
UPDATE >>>
You're right... the ToolTip was still on the TextBlock. Then you just need to update your ToolTip.Binding to *the same value that works on the Text property:
<ListView ItemsSource="{Binding Tests}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding ToolTip}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Title" Text="{Binding Title}"
ToolTip="{Binding ToolTip}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Now you should see 2 tooltips, one when over the TextBlock and one when over the ListViewItem.
UPDATE 2 >>>
#Ron, I really cannot understand why you are taking such a negative reaction to my answer(s)... you really should watch your attitude, because I am trying to help you and I don't feel that I deserve your bad attitude. So, to address your second, even ruder comment:
I said that the HorizontalAlignment is set to Stretch by default
Really? Where did you say that? In fact, you didn't say that, you said The ListViewItem stretches on default, which is something entirely different. As mentioned in the comment, I was stretching the TextBlock inside the ListViewItem with the HorizontalContentAlignment property, which isn't set to Strecth by default.
Who said that I want the Title as my ToolTip?
Nobody said that, but you did say The ToolTip's value is dynamically generated... so I can only image that you are Binding your dynamically generated ToolTip. If this is so, then you can simply data Bind that same value to the ListViewItem.ToolTip property as well.
UPDATE 3 >>>
In response to your last comment:
I stick to my question from the beginning because I cant really explain the problem. I know whats the solution though I dont know the practical way. I want to bind to the TextBlock's ToolTip Property.
Well sorry, but you can't do that in XAML because the TextBlock is declared in a DataTemplate. You can only access DataTemplate generated elements in code because they don't just exist until runtime... see the How to: Find DataTemplate-Generated Elements page on MSDN to find out how to do that. So you'll have to find another way to achieve your goal and that's why I've been suggesting these other methods all along.

ComboBoxItem Selection Area Issue

I have a comboBox with a ComboBox.ItemTemplate
<ComboBox>
<ComboxBox.ItemTemplate>
<DataTemplate DataType="{x:Type ViewModel}">
<TextBlock Text="1" />
</DataTemplate>
</ComboxBox.ItemTemplate>
</ComboBox>
The Item renders properly, but when I try to select the ComboxItem, the selection is only available on "1" rest of the Area in the ComboBoxItem is not clickable.
How do I set up the code so the selection can happen on the whole item and not just the Textblock.
Your ComboBox/ComboBoxItem seems to be templated, by default the highlight brush is a deeper blue. If you have access to the templates make sure the content of the ComboBoxItem stretches horizontally.
If the template is bound "correctly" setting the content-alignments may be enough.
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ComboBox.ItemContainerStyle>

Conditionally changing the Foreground of a WPF ComboBox item depending upon a value in the databound ItemsSource item

I have a WPF ComboBox bound to a Collection List<Users>. I have applied a DataTemplate to show the FirstName using a TextBlock and this works as expected:
<ComboBox Margin="5" ItemsSource="{Binding Path=TheUsers}" Name="cboUsers">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10" Text="{Binding Path=FirstName}">
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>`
I have an item in my User class called IsActive which is a Boolean value. If true then I want to set the Foreground of the TextBlock to Navy.
I have spent so much time on what should be so easy and looked all over the web but most articles talk about changing the overall colour or binding to another element in the xaml.
I tried implementing a DataTrigger and after an hour removed the code because it was not working. It would not recognise my field name. Does anyone have a very simple guide to how to do this or what would be the best approach?
As you apparently are not dealing with fields after all, this style should do what you want:
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Foreground" Value="Navy"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
It would not recognise my field name.
You cannot bind to fields, end of story.

Problem getting custom content in a TabItem visible

I have a custom ItemsControl (WorKArea) that marks all items it has into a WorkSheet instance.
I have a style for the ItemsControl that uses a TabControl to show the content. Every sheet creates a tab. The style is:
<Style TargetType="{x:Type local:WorkArea}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:WorkArea}">
<TabControl ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:WorkArea}}, Path=Items}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding Title}" />
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So far so good. The "sheets" show up, and the title is properly bound to the Header.
How can I get the tabs showing the content now? Whatever I try, nothing shows up at all for every WorkSheet - the content is always empty. Anyone the proper code?
Your work area should provide a ContentTemplate property and the TabControl should have a TemplateBinding which to it.

How to set the DataContext on a DataGrid Column Header

In my Silverlight 3 user control I am showing a basic DataGrid control. I need to generate the columns programmatically as follows:
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
dataGrid.Columns.Add(col);
The style is defined as follows:
<Style x:Name="ColumnStyle" x:Key="ColumnHeaderStyle"
TargetType="prim:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Loaded="StackPanel_Loaded">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Data}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I want to set the data context of the header to a "header" object (with "Name" and "Data" properties which are referenced in the DataTemplate). Unfortunately, I cannot use the StackPanel_Loaded event as suggested elsewhere, because the event handler is also called when the user starts a column drag&drop operation.
What is the correct way of setting the DataContext of a DataGrid column header?
Here's how you would do it in XAML (this works in WPF; not sure if it works in SL)
<DataGridTextColumn Binding="{Binding Path=Discount}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Content" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.DiscountHeader}" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
Turns out that one can use the Header property (which is of type Object) as the DataContext for the DataTemplate (set as shown above):
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
col.Header = myHeaderDataContext; // DataContext for ColumnHeaderStyle
dataGrid.Columns.Add(col);
Based on Matt's answer, I came up with the solution of binding the header on the DataGridCellsPanel which in Snoop appeared to have the correct data context :
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource CenterAlignedColumnHeaderStyle}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
And this is non intrusive in the way that you can still inherits from custom styled headers (see exemple above) or event the base column header style:
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
This solution has the advantage of being pure and clean XAML and to refer to the closest ancestor holding the correct datacontext rather than trying to reach datacontext of top hierarchy elements like UserControl.

Resources