From what I understand, ListView has 2 themeing styles, one that it uses when you don't specify a View and one it uses when you do.
<HeaderedContentControl Header="No GridView" Margin="10">
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>A</sys:String>
<sys:String>B</sys:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</HeaderedContentControl>
<HeaderedContentControl Header="GridView"
Margin="10">
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Header="Content" />
</GridView>
</ListView.View>
<ListView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>A</sys:String>
<sys:String>B</sys:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</HeaderedContentControl>
How do I style these? .. for example if I was making a custom theme?
I thought I would take a look at an existing theme, so I've downloaded the Luna theme from https://msdn.microsoft.com/en-us/library/aa972127(v=VS.90).aspx and added it as a resource. (I've added a button so you can see it is indeed using the luna theme)
But you'll notice that the Listview, other than the column header bit is the same. So it appears that the GridView styling in the luna theme isn't even used? I can go in and change the GridViewItemContainerStyleKey and it has no affect. It always appears to use the aero style
For reference, here is the GridView styling taken from the Luna theme :
<Style x:Key="{x:Static GridView.GridViewStyleKey}"
TargetType="{x:Type ListView}">
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush"
Value="{StaticResource ListBorder}"/>
<Setter Property="BorderThickness"
Value="1"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility"
Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll"
Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}"
Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false"/>
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Static GridView.GridViewItemContainerStyleKey}"
TargetType="{x:Type ListViewItem}">
<Setter Property="Background"
Value="Transparent"/>
<Setter Property="VerticalContentAlignment"
Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<GridViewRowPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="true">
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected"
Value="true"/>
<Condition Property="Selector.IsSelectionActive"
Value="false"/>
</MultiTrigger.Conditions>
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just dump the complete control template out using Expression Blend. The ones on MSDN aren't the real ones.
The header control items are GridiewColumnHeader controls. So you just target them as you normally would:
<Window.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
This will turn your header red. If you want to dump out the real "runtime" template in Blend...
1) go into the XAML
2) update client XAML to:
<Grid>
<GridViewColumnHeader />
</Grid>
3) View | Objects & Timelines
4) You should see your window hierarchy there...
Window
Grid
GridViewColumnHeader
5) Select GridViewColumnHeader
6) Right click | Edit Template | Edit A Copy | OK
Then just modify / clean it up / refactor as you like.
Oooooooooooohhh... that is a ListViewItem. The GridView items are the column headers. What I did for that was have a "main" ListViewItem style and use a trigger that points to the ListView.View and if its x:Null, I assume its the normal view and set the template to my normal view template, otherwise set it to my GridView template. I do the same thing for having a themed and non themed version. So I actually have 4 templates.
Related
I am new to XAML and WPF and so far I found a lot of good explanations on SO for different things I needed during my work on the project. I come from the web area where I have a lot of experience making graphic elements layouts for web pages using CSS. What really frustrates me is that I have no idea how make some custom nice looking UI in a WPF page, when I get a mock file (as attached).
In particular to this file, I need to place buttons which have a border on the left and an additional square on the right. The color of both depends on the button state. If the button is pressed, the color of the left border and right square should be green (as depicted in the screenshot).
Is there any way similar or at least near to CSS that I coud use to achieve this?
Your general layout suggests that you have a collection of states that you want ot be represented as a list of buttons. These buttons should be togglable and display green when toggled. In this case, an ItemsControl would be suitable, since you do not want or need selection, but interaction with buttons.
For the buttons itself, there is a lot more to do. The visual representation and state are defined in a control template. You can either create a new one from scratch or copy the default control template and adapt it. Here I have created a control template for ToggleButton that reflects your mockup.
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" StrokeDashArray="1 2" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" StrokeThickness="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="Black"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="LawnGreen"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="Black"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="DarkGreen"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="Black"/>
<SolidColorBrush x:Key="Button.IsChecked.Background" Color="Green"/>
<SolidColorBrush x:Key="Button.IsChecked.Border" Color="Black"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="Lr" Grid.Column="0" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}" Width="20" Height="40"/>
<Border x:Name="Bd" Grid.Column="1" Background="Transparent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<Rectangle x:Name="Rr" Grid.Column="2" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}" Width="40" Height="40" Margin="40, 0, 0, 0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="true">
<Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="Lr" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="Fill" TargetName="Rr" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Button.MouseOver.Border}"/>
<Setter Property="Stroke" TargetName="Lr" Value="{StaticResource Button.MouseOver.Border}"/>
<Setter Property="Stroke" TargetName="Rr" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" TargetName="Lr" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="Fill" TargetName="Rr" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Button.Pressed.Border}"/>
<Setter Property="Stroke" TargetName="Lr" Value="{StaticResource Button.Pressed.Border}"/>
<Setter Property="Stroke" TargetName="Rr" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Fill" TargetName="Lr" Value="{StaticResource Button.IsChecked.Background}"/>
<Setter Property="Fill" TargetName="Rr" Value="{StaticResource Button.IsChecked.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Button.IsChecked.Border}"/>
<Setter Property="Stroke" TargetName="Lr" Value="{StaticResource Button.IsChecked.Border}"/>
<Setter Property="Stroke" TargetName="Rr" Value="{StaticResource Button.IsChecked.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Lr" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="Fill" TargetName="Rr" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="Stroke" TargetName="Lr" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="Stroke" TargetName="Rr" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In essence, the control template consists of a Grid that host two rectangles for the state color, and a ContentPresenter in between that shows the content. There are triggers for the different states, that set the color of the rectangles accordingly. The toggled state is active when IsChecked is true, IsPressed is active as you are pressing the mouse button on the button.
For more information on how to create custom control templates, please refer to the documentation.
How to create a template for a control (WPF.NET)
Now you need to create an ItemsControl, bind your collection and add a DataTemplate. The data template defines how the data items are represented, see Data Templating Overview.
<DockPanel>
<Border DockPanel.Dock="Top"
BorderBrush="Black"
BorderThickness="1"
Margin="0, 0, 0, 40">
<TextBlock Text="States"
TextAlignment="Center"/>
</Border>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding StringItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton Content="{Binding}"
Style="{StaticResource ToggleButtonStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
That is it and this is what the result looks like:
I have a WPF ListView that I'm trying to apply a custom style too... primarily I want to make the background of the listview box transparent with no border... and I want to override the highlighted and selected item styles. The default highlight is a semi-transparent blue and the selected item is grey. I'd like to override these in order to customize them. I've followed several threads and tutorials... including this one but, my highlight and selected items remain in the default style. Here's what I have.
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="ListViewStyle" TargetType="ListView">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green" />
</Style.Resources>
</Style>
</ResourceDictionary>
</UserControl.Resources>
....
<ListView Style="{StaticResource ListViewStyle}" ItemsSource="{Binding Path=Items}" ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectedItem="{Binding Path=DataContext.Current" >
<ListView.ItemTemplate>
<DataTemplate DataType="local:Cases">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<!-- Some UI Controls Here -->
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This approach of trying to override the system colours doesn't work on Windows 8 and later.
You need to modify the ControlTemplate of the ListViewItem container.
You can copy the default template into your XAML markup by right-clicking on the ListView in design mode in Visual Studio or in Blend and choose Edit Additional Templates->Edit Generated Item Container (ItemContainerStyle) and then edit it as per your requirements by for example changing the Color properties of the SolidColorBrushes:
<ListView ItemsSource="{Binding Path=Items}" SelectedItem="{Binding Path=DataContext.Current" >
<ListView.Resources>
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="Red"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate DataType="local:Cases">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<!-- Some UI Controls Here -->
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Before I post my code let me post image where you can easily notice what's acctually happening:
And as you can see on text boxes, border thickness is not same on every side.
In case of textbox it is much more brighter on the right for example.
Also on combobox there is something like shadow on top and on left side..
How could I fix this, I simply want 1px blue border around my controls..
And here is my code:
<ComboBox Name="cmbComboBoxOne" Height="40" BorderThickness="1" VerticalAlignment="Center" BorderBrush="#0091EA" ></ComboBox>
<TextBox Name="txtTextBoxOne" TextWrapping="Wrap" Text="TextBox" BorderThickness="1" BorderBrush="#0091EA" />
EDIT:
I applied Edit Template Copy, I set border thickness to 1 and colour to purple, and it looks like this:
So guys, again it is not good with thickness:1 px, for example with thickness:2px its awesome, all sides are equal but 2px is too much for me..
Here is my code after I edited template:
<TextBox x:Name="txtName" Grid.Column="1" SnapsToDevicePixels="True" UseLayoutRounding="True" Grid.Row="0" Margin="5,0,10,0" TextWrapping="Wrap" Text="TextBox" Height="40" VerticalAlignment="Center" Style="{DynamicResource TextBoxStyle1}" >
<TextBox.Resources>
<Style x:Key="TextBoxStyle1" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Purple"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" BorderStyle="Sunken" Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost"/>
</Microsoft_Windows_Themes:ClassicBorderDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>
as you can see guys
<Setter Property="BorderBrush" Value="Purple"/>
<Setter Property="BorderThickness" Value="1"/>
are set, but result is somehow same :/
Try to set the SnapsToDevicePixels and/or UseLayoutRounding properties to True:
<ComboBox Name="cmbComboBoxOne" ... SnapsToDevicePixels="True" UseLayoutRounding="True" />
If this doesn't work you could try to modify the control template of the controls. Right-click on them in design mode in Visual Studio 2012+ or Blend and choose Edit Template->Edit a Copy to copy the default templates into your XAML markup and then set the above properties on the Border elements in the generated templates.
Edit: Replace the ClassicBorderDecorator with an ordinary Border element:
<TextBox x:Name="txtName" Grid.Column="1" SnapsToDevicePixels="True" UseLayoutRounding="True" Grid.Row="0" Margin="5,0,10,0" TextWrapping="Wrap" Text="TextBox" Height="40" VerticalAlignment="Center" Style="{DynamicResource TextBoxStyle1}" >
<TextBox.Resources>
<Style x:Key="TextBoxStyle1" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Purple"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>
If you want to customize textbox and combobox border you need to change default style and template of these controls by right click on control and select edit template.
I want to create a custom control type that behaves exactly like a ListBox, except that it displays with a heading above it.
I think what I need to do is inherit from ListBox and use code like the following:
var originalTree = Template.VisualTree;
var panel = new FrameworkElementFactory(typeof(StackPanel));
var heading = new FrameworkElementFactory(typeof(TextBlock));
heading.SetValue(TextBlock.TextProperty, "Heading");
panel.AppendChild(heading);
panel.AppendChild(originalTree);
Template.VisualTree = panel;
Except wherever I tried to place it, it didn't work, because Template.VisualTree was null. What am I doing wrong?
As far as i know templates can be defined in various ways, if the VisualTree is null, it has been generated 'by reference', in that case it has been set with Frameworktemplate.Template.
(Editing that is not intended, all members are internal or private)
I would use a UserControl if you are going to take the whole root anyway.
Edit: Copying and editing the default template should be fine as well, here is the default style:
<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
<Style TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(You could bind the header TextBox.Text to the ListBox.Tag then you do not need to subclass it)
Default templates and styles are on MSDN.
This article http://www.wpftutorial.net/CustomVsUserControl.html implies that a UserControl is a conglomerate of several controls - in your case a Label or TextBlock plus a ListBox? So is a user control a possible solution?
I have a <ListBox> with custom <ListBox.ItemTemplate> and <DataTemplate> in it:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="5">
<Image Source="{Binding Picture}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now when I'm choosing the ListBoxItem it gets ugly with blue colored row selection. I'd like to change it. I want to color only border's background and nothing else. Also I want to change MouseOver behavior. I've tried trough triggers, but ContentPresenter doesn't have Background property.
UPD:
Well, I've managed to change the background on MouseEnter and MouseLeave:
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard >
<ColorAnimation Storyboard.TargetProperty="Background.Color"
To="LightBlue" Duration="0:0:0.03"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
But still can't change the Background when item's selected. I'm trying through:
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
Doesn't work
The coloring you're looking for is in two Triggers inside the template for ListBoxItem, not the ItemTemplate. To change this you need to edit the ItemContainerStyle for the ListBox. This is the default that can be used as a starting point:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
You can do this by using triggers. I have in one of my projects something like this:
<Trigger Property="IsSelected" Value="true">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemSelectedBackground}"/>
</Trigger>
Though it doesn't change Border color, it shows how to change the Background. So, maybe try to set this to null. This triggers are part of a custom Style in which a tracking is achieved using IsMouseOver property.
HTH