Reputation: 3658
I have written a user control which consists of a ListBox and a couple extra controls. I want to wrap the whole thing in a border using the same brush as a standard ListBox would have.
MSDN has a page given a standard style for the ListBox, but it has hardcoded colours whereas a standard ListBox uses different styles on different platforms or with different themes. How can I recreate the border of a ListBox in my own control?
Upvotes: 2
Views: 654
Reputation: 3658
What I've done is to write a function that extracts the default style for a control, and the relevant property from that style:
private static TReturn ExtractStyleProperty<TReturn, TFromControl>(string name, TReturn defVal)
{
var style = Application.Current.FindResource(typeof(TFromControl)) as Style;
if (style == null){
return defVal;
}
var setter = style.Setters.Where(s => s is Setter).Cast<Setter>().First(s => s.Property.Name.Equals(name));
if (setter == null){
return defVal;
}
return (TReturn)setter.Value;
}
With that I can create a property for each property I want to recreate:
public Brush ListBoxBorderBrush {
get {
return ExtractStyleProperty<Brush, ListBox>("BorderBrush", new SolidColorBrush(Color.FromRgb(130, 135, 144)));
}
}
And then bind my control's properties to those ones. This gets the value appropriate to the system and WPF theme.
Upvotes: 0
Reputation: 7951
I used Microsoft Expression Blend to create a copy of the standard ListBox template. Here's what I got from it...
<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
<Style x:Key="ListBoxStyle2" 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 should be able to use the same brushes in this default style to get the brushes related to the current theme.
Upvotes: 2