views:

263

answers:

1

I'm curious if anyone knows of a way to easily get a double border effect in WPF similar to what you see in the selected items in Windows Explorer in Windows 7.

Example of what I'm looking for

If you look closely, you'll notice that the selected item has a dark border, a lighter, inner-border, and then a gradient background.

Currently, I'm using two borders around an object any time I want to achieve this effect. Doing it that way is ugly syntactically and really muddies my view xaml. Being a web developer at heart I'd like to separate the xaml structure from the style as much as possible. So, I've started putting this into Styles and Content Templates in order to pull it out of my view xaml.

However, I'm curious if there may be a better way to go about this.

I played around for a while using a VisualBrush as a background to try to get the effect. However, I want to be able to apply the background to elements that can be any size and the way the VisualBrush stretched the visual to fit the element background didn't work the way I wanted it to. Essentially, I'd really just like it to stretch the visual the way the WPF layout system would do it.

Any ideas would be greatly appreciated.

-- Dusty

A: 

A VisualBrush is probably not what you want to do in this scenario, as it's pretty heavy.

You can solve the problem with some Xaml without nesting borders.

For example,

<Border BorderBrush="#FF00B5C5" BorderThickness="1" CornerRadius="2" Background="White">
   <Grid Background="#FF00B5C5" Margin="1">
     <Rectangle Fill="#FFA2F2FE" />
     <TextBlock Text="This is some text" VerticalAlignment="Center"/>
   </Grid>
</Border>

You can, of course, tweak the properties to get the look you need.

EDIT: If you want to create a style, so you can reskin the look-and-feel, you can do something like this:

<Window.Resources>
    <Style x:Key="BorderedTextBlock" TargetType="ContentControl">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border BorderBrush="#FF00B5C5" BorderThickness="1" CornerRadius="2" Background="White"> 
                       <Grid Background="#FF00B5C5" Margin="1"> 
                         <Rectangle Fill="#FFA2F2FE" /> 
                         <TextBlock Text="{Binding}" VerticalAlignment="Center"/> 
                       </Grid> 
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid x:Name="LayoutRoot">
    <ContentControl Style="{StaticResource BorderedTextBlock}" Content="This is some text" Width="200" Height="24"/>
</Grid>

Additionally, turn this into a custom control with all the styling and theming parameters that you need.

Hope that helps,

Sergio

SergioL
While not exactly what I was looking for, your advice is sound. I suppose using a VisualBrush probably isn't all that performant.
dustyburwell
I don't think you'd ever get the VisualBrush to look exactly how you want because of the stretching factor. As scales up to fill an element, the "fake" border will scale up too, so you won't get that nice 1 pixel white border on the inside. Styles and Themes (and possibly a custom control) are the way to go here to eliminate the redundancy and mess.
SergioL
I appreciate that advice, SergioL. I hadn't really given it much thought, but that's exactly what a lot of the standard ControlTemplates do. For instance, Button uses ButtonChrome in Luna and Aero for it's border. Thanks for jogging my brain on that one.
dustyburwell