I made a custom styled list in WPF:
<DataTemplate x:Key="SelectedTemplate">
<StackPanel Background="#FF4E4E4E" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Path=Title}" Foreground="#FFD80000" />
</StackPanel>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate"
Value="{StaticResource ItemTemplate}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate"
Value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
...
<ListBox
Name="lbSongs"
DockPanel.Dock="Left"
ItemsSource="{Binding Path=SongDirectory}"
SelectedItem="{Binding Path=Song, Mode=TwoWay}"
Visibility="{Binding Path=ListVisibility}"
ItemContainerStyle="{StaticResource ContainerStyle}"
HorizontalContentAlignment="Stretch"
Width="180px" Background="#FF333333" />
I tried to make a custom style for the selected item. To make the selection bar stretch to the width of the ListBox, I set the ItemContainerStyle's HorizontalContentAlignment property to "Stretch". The problem is that it does not stretch fully, a tiny bar on the left still remains and the original (blue) selection bar is still visible there. See the screenshot:
How can I make it to stretch to full size? Or how can I style the original selection bar?
Thanks in advance.
Just set the Padding for the ListBoxItem to zero. That blue bar should disappear.
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="Padding" Value="0"/>
...
</Style>
Another option is just to re-write the ControlTemplate for the ListBoxItem so that you'll have better control on how it looks like. But yeah, this may not be necessary in your case.
Related
I would like to change the expanders background color to a lighter variant on mouse hover. So I figured I use a trigger and a converter to convert the background color to a lighter variant on mouse over. I started simple and only implement the trigger. That works:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Expander}">
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Expander Header="Header">
<StackPanel>
<TextBox Background="Transparent">Content</TextBox>
</StackPanel>
</Expander>
</StackPanel>
So I can achieve almost what I want. But I want to be able to set the color on the expander like this:
<Expander Header="Header" Background="Yellow">
The moment I add that the color switching stops working and the expander is always yellow. Why is that happening and how can I achieve my goal?
Edit: in my final application I will have an itemscontrol with multiple expanders whose background color is databound to my view model, so I think I cannot set the color in the style.
<ItemsControl ItemsSource="{Binding TestStepDescriptions}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type localVMsTestEngines:AutomaticTestStepDescription}">
<Expander Background="{Binding StepStatus, Converter={StaticResource StepStatusToColorConverter}}">
regards,
Jef
You cannot set that color in the Expander directly if you use a Trigger.
Instead you have to do it like this:
<ItemsControl ItemsSource="{Binding TestStepDescriptions}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type localVMsTestEngines:AutomaticTestStepDescription}">
<Expander >
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Background" Value="{Binding StepStatus, Converter={StaticResource StepStatusToColorConverter}}"/>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Expander.Style>
</Expander>
Usage
<Expander Header="Header">
I want to set the text color for PASS as GREEN and the text color for FAIL as RED. I can't seem to find the solution. I need to do this in pure XAML.
<ComboBox x:Name="LocatedCorrectly" Width="100"
Height="25" Grid.Column="1" Grid.Row="2"
HorizontalAlignment="Left"
IsSynchronizedWithCurrentItem="True">
<ComboBoxItem Content="PASS" Tag="PASS" IsSelected="True"/>
<ComboBoxItem Content="FAIL" Tag="FAILED" />
</ComboBox>
You can Use Triggers for the same (you should inherit the base style too)
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="Content" Value="PASS">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
I would suggest altering your style by creating style document separately in Window.Resources, and then styling your ComboBox items to have whatever foreground color you want.
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</ComboBox.Resources>
If you want to keep it in Application.Resources, then I think you need to track down what x:Static brush key is used for setting the TextBlock.Text color and overwrite that in your ComboBox.Resources
I need to define a global style for all TextBlock and TextBox that exist within ItemsControl elements.
I need all the TextBlock elements to have a Width of 100 and Left aligned, and the TextBox elements to have a width of 50 and to be Right aligned.
How can I achieve this?
I don't understand your "that exist within ItemsControl elements" but if you are talking about your ItemsTemplate it should work like this
<Style x:Key="myTextBoxStyle">
<Setter Property="Width" Value="50"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style x:Key="myTextBlockStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<ItemsControl>
<ItemsControl.ItemsTemplate>
<DataTemplate>
<Grid>
<TextBlock Style="{StaticResource myTextBlockStyle}"/>
<TextBox Style="{StaticResource myTextBoxStyle}"/>
<Grid>
<DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
This will display all items in your ItemsControl with a textbox which uses your myTextBoxStyle and your textblock with the myTextBlockStyle.
you can declare the style inside the ItemsControl.Resources as well
<ItemsControl ItemsSource="{Binding Persons}">
<ItemsControl.Resources>
<Style x:Key="TxtBlk1" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="red"/>
<Setter Property="FontSize" Value="56"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Style="{StaticResource TxtBlk1}"></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have a combobox that i need to edit its error template to show a red border when there is a validation error.
I am using the following style
<Style TargetType="{x:Type ComboBox}" >
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Border BorderBrush="Red" BorderThickness="3">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
The border never shows up when validation errors occur. Any tips what is going wrong?
The Style you posted works. You should check your binding, did you add ValidatesOnDataErrors=True and ValidatesOnExceptions=True to the binding of SelectedValue?
enter code heretry without the dock panel, that is uneuseful since it wraps jus one element. However, sicnecerely I don't wnow if it makes sense to wrap a textbox with a border, since it has already a border! You should try to change directly the colour of its border. You could try to use again the panel but then put the border around the panel ie:
Border BorderBrush="Red" BorderThickness="3"
DockPanel
AdornedElement
This makes more sense because the wrap panel has not its own border.
Use This.
<Style x:Key="textBoxStyle" TargetType="{x:Type telerik:RadMaskedTextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Control.BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
I don't like any of the responses here. Simply put, how do you change the border color for the error template for a ComboBox using Blend or not? It shouldn't be acceptable to draw another border around the existing border of the ComboBox. I've figured out how to creat a ControlTemplate in Blend but not a Validation Template.
I've come close with trying to make it appear like I've changed the actual border color, but that's not what I actually want. Suggestions? To complicate it a bit, I'd like to display a red asterisk outside of the right border of the control.
The following code is a close attempt, but it is actually drawing a border inside the ComboBox and if you look close, you can see that the border is 2 pixels wide when combined with the ComboBox border:
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder>
<Border BorderBrush="Blue" BorderThickness="1" CornerRadius="2" />
</AdornedElementPlaceholder>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
I searched around some more and came up with a solution based on another article here: WPF - How to apply style to AdornedElementPlaceholder's AdornedElement?
<!-- This works -->
<ComboBox Name="comboBox1" Style="{StaticResource NewComboBoxStyle}" Validation.ErrorTemplate="{StaticResource comboBoxValidationTemplate}" />
<SolidColorBrush x:Key="MainBorderBrush">#FF91B3FF</SolidColorBrush>
<Style x:Key="NewComboBoxStyle" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource myErrorTemplate}">
<Setter Property="BorderBrush" Value="{DynamicResource MainBorderBrush}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
<!-- Sets ToolTip when Validation.HasError is True. -->
<Style TargetType="Control" x:Key="myErrorTemplate">
<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>
<ControlTemplate x:Key="comboBoxValidationTemplate">
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder/>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
</ControlTemplate>
I have a DataGrid style in App.xaml:
<Style TargetType="{x:Type DataGrid}">
<Setter Property="Foreground" Value="{StaticResource DataGridItemTextBrush}" />
<Setter Property="VerticalGridLinesBrush" Value="{StaticResource GridBrush}" />
<Setter Property="HorizontalGridLinesBrush" Value="{StaticResource GridBrush}" />
<Setter Property="RowBackground" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="AlternatingRowBackground" Value="#77000000" />
</Style>
This works great for all of my datagrid's in my applications.
However, for one of my datagrids, I want to group my rows if a specific column shares the same values. So I use the following on that particular datagrid:
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Name}" Padding="3"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander>
<Expander.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White" />
</Style>
</Expander.Resources>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name, StringFormat=Set: {0}}" Margin="5,0"/>
<TextBlock Text="{Binding Path=ItemCount, StringFormat=(\{0\} Games)}"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
Problem: Now this DataGrid displays everything correctly based on my DataGrid style, except it displays the text (foreground) as black instead of my style.
Solution: I can fix the problem (though I don't understand why this is necessary) by modifying my ItemsPresenter to either of the following:
<ItemsPresenter TextElement.Foreground="{StaticResource DataGridItemTextBrush}"/>
or
<ItemsPresenter TextBlock.Foreground="{StaticResource DataGridItemTextBrush}" />
Question: Can anyone explain why this happens and/or offer a better solution that will guarantee that my ItemsPresenter does not override any of my DataGrid styles?
Thank you!
Styling cascades down unless the child opts to override the imposed style. The ItemsPresenter in your case has default values; which you are not overriding within your DataGrid style. Either create an ItemsPresenter style within App.xaml to meet your needs or modify the value locally via an explicit or implicit style, or opt for your proposed solution.
Also keep in mind that you can use the BasedOn property to inherit the default styling; overriding only certain properties.
BasedOn="{StaticResource {x:Type DataGrid}}"