locked
Style a Border Brush RRS feed

  • Question

  • How do I make a Style for all Borders. In particular, how do I set the BorderBrush in the style?

    I couldn't find the default Style for Border, even in Blend.

    Saturday, December 12, 2015 3:43 PM

Answers

  • Ah yes, I forgot about that. ( I do more WPF and asp.net mvc nowadays.)

    Bad news, I'm afraid.

    Implicit styles do not propagate into datatemplates. Or not consistently anyhow.

    If I set mine up in a dictionary merged in app.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SilverlightApplication1"
        >
        <Style TargetType="Border">
            <Setter Property="BorderBrush" Value="Yellow"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Style>
    
    </ResourceDictionary>

    Then do:

        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.Resources>
                <DataTemplate DataType="local:TestObject">
                    <Border>
                        <TextBlock Text="Hello world!"/>
                    </Border>
                </DataTemplate>
            </Grid.Resources>
            <StackPanel>
                <Border>
                    <TextBlock Text="First Test"/>
                </Border>
                <ContentControl>
                    <local:TestObject/>
                </ContentControl>
            </StackPanel>


    I get a yellow border round the first one and none visible on the second ( from the datatemplate ).

    You need to give them a key and use that explicitly.

    The approach used in the Silverlight toolkit is to create a base style with a key and used basedon for an implicit style.

    A connect issue was raised for this and there was some reason given for rejecting it, I think they said it was by design but I may be mistaken.

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SilverlightApplication1"
        >
        <Style TargetType="Border" x:Key="BaseBorder">
            <Setter Property="BorderBrush" Value="Yellow"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Style>
        <Style TargetType="Border" BasedOn="{StaticResource BaseBorder}"/>
    </ResourceDictionary>

    and

        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.Resources>
                <DataTemplate DataType="local:TestObject">
                    <Border  Style="{StaticResource BaseBorder}">
                        <TextBlock Text="Hello world"/>
                    </Border>
                </DataTemplate>
            </Grid.Resources>
            <StackPanel>
                <Border>
                    <TextBlock Text="First Test"/>
                </Border>
                <ContentControl>
                    <local:TestObject/>
                </ContentControl>
            </StackPanel>

    Both now get a yellow border.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    • Proposed as answer by mltiede Monday, December 14, 2015 2:10 PM
    • Marked as answer by Mark Tiede Monday, December 14, 2015 3:24 PM
    Monday, December 14, 2015 1:51 PM
    Moderator

All replies

  • Blend will give you default templates rather than styles. There is no default style specifically for a border.

    A border has no default template.

    .

    Silverlight 5 introduced generic styles which were previously wpf only.

    They allow you to define a style without a key on a TargetType.

    You can define such a style in a resource dictionary and merge it in app.xaml.

    That style will then be applied to all controls of that targettype in your app.

    In a resource dictionary:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style TargetType="Border">
            <Setter Property="BorderBrush" Value="Gray"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Style>
    </ResourceDictionary>

    Note that borderbrush is a brush rather than just a colour and you can use fancy pictures and stuff rather than just a plain colour. There is a converter at work which is turning  gray into a brush.

    You then merge that in app.xaml

    <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                 x:Class="SilverlightApplication1.App"
                 >
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Dictionary1.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>

    And then any border you use will be gray.

    Unless you set a value in the markup for it, that will over-ride the value in the style.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles


    Sunday, December 13, 2015 11:51 AM
    Moderator
  • Yeah, that is what *I* thought. But it didn't work. When I do this:

       <UserControl.Resources>
          <viewmodels:Viewmodel x:Key="Viewmodel1"/>
    
          <Style TargetType="Border">
             <Setter Property="BorderBrush" Value="Yellow"/>
          </Style>
          <DataTemplate DataType="viewmodels:StandardMapGeneral">
             <Grid x:Name="LayoutRoot" DataContext="{Binding Properties}">
                <Grid.ColumnDefinitions>
                   <ColumnDefinition Width="Auto"/>
                   <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Border BorderThickness="1" HorizontalAlignment="Left">
    

    No border shows up.  If I PUT the BorderBrush on the Border tag itself, it DOES show up with that color.

    Monday, December 14, 2015 1:12 PM
  • Ah yes, I forgot about that. ( I do more WPF and asp.net mvc nowadays.)

    Bad news, I'm afraid.

    Implicit styles do not propagate into datatemplates. Or not consistently anyhow.

    If I set mine up in a dictionary merged in app.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SilverlightApplication1"
        >
        <Style TargetType="Border">
            <Setter Property="BorderBrush" Value="Yellow"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Style>
    
    </ResourceDictionary>

    Then do:

        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.Resources>
                <DataTemplate DataType="local:TestObject">
                    <Border>
                        <TextBlock Text="Hello world!"/>
                    </Border>
                </DataTemplate>
            </Grid.Resources>
            <StackPanel>
                <Border>
                    <TextBlock Text="First Test"/>
                </Border>
                <ContentControl>
                    <local:TestObject/>
                </ContentControl>
            </StackPanel>


    I get a yellow border round the first one and none visible on the second ( from the datatemplate ).

    You need to give them a key and use that explicitly.

    The approach used in the Silverlight toolkit is to create a base style with a key and used basedon for an implicit style.

    A connect issue was raised for this and there was some reason given for rejecting it, I think they said it was by design but I may be mistaken.

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SilverlightApplication1"
        >
        <Style TargetType="Border" x:Key="BaseBorder">
            <Setter Property="BorderBrush" Value="Yellow"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Style>
        <Style TargetType="Border" BasedOn="{StaticResource BaseBorder}"/>
    </ResourceDictionary>

    and

        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.Resources>
                <DataTemplate DataType="local:TestObject">
                    <Border  Style="{StaticResource BaseBorder}">
                        <TextBlock Text="Hello world"/>
                    </Border>
                </DataTemplate>
            </Grid.Resources>
            <StackPanel>
                <Border>
                    <TextBlock Text="First Test"/>
                </Border>
                <ContentControl>
                    <local:TestObject/>
                </ContentControl>
            </StackPanel>

    Both now get a yellow border.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    • Proposed as answer by mltiede Monday, December 14, 2015 2:10 PM
    • Marked as answer by Mark Tiede Monday, December 14, 2015 3:24 PM
    Monday, December 14, 2015 1:51 PM
    Moderator
  • Ah, so it isn't something I'm doing wrong. I'll add a key, but I was hoping not to have to do that cause I've got quite a few of them, hence my desire to USE the implicit Style. Oh well.

    Thanks.

    Monday, December 14, 2015 2:10 PM
  • You're doing it right, it just isn't as developer friendly as any other xaml implicit style.

    Did you mean to mark that post as answer?

    You've proposed it instead, which seems a bit odd.

    As the person starting the thread you're the one marks an answer.

    Unless you never get round to it and then a mod will mark the post eventually so that people can see there is an answer in the thread.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Monday, December 14, 2015 3:15 PM
    Moderator
  • I have two IDs. One for work and one personal. The browser automatically logs me in and unless I pay attention, I might be in as the personal one instead of the work one.  That happened here.  I created it from the personal one and later when I went in with the work one, my only choice was to "recommend".  I've logged in now with the one I created the post with and marked it as answer.
    • Edited by Mark Tiede Monday, December 14, 2015 3:27 PM
    Monday, December 14, 2015 3:26 PM
  • I'm having a related problem. With all of the datatemplates working in the page's resource, it was getting messy with all those datatemplates, so I decided to move them out to separate files and then suck them into a mergeddictionary. Only trouble is the same datatemplate that worked in the page's resource, doesn't work from the file.

    Here is the resource (I tried setting Page and Resource property for the file, but it didn't make any difference).

    <ResourceDictionary
        
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:viewmodels="clr-namespace:VSDSConfig.Viewmodels"
       >
       <Style TargetType="Border" x:Key="BB">
          <Setter Property="BorderBrush" Value="Gray"/>
          <Setter Property="BorderThickness" Value="1"/>
       </Style>
    
       <DataTemplate DataType="viewmodels:StandardMapGeneral">
         etc.
       </DataTemplate>
    
    
    </ResourceDictionary>

    And here is where it was referenced:

    <?xml version='1.0' encoding='utf-8' ?>
    <UserControl  
       
       
       x:Class="VSDSConfig.MainPage"
       
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       
       xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
       xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" 
    
       xmlns:local="clr-namespace:VSDSConfig.Parts.MainView"
       xmlns:viewmodels="clr-namespace:VSDSConfig.Viewmodels"
       xmlns:converters="clr-namespace:VSDSConfig.Converters"
       
       xmlns:rest="clr-namespace:VSDS.Settings.StandardMap"
       >
       <UserControl.Resources>
          <viewmodels:Viewmodel x:Key="Viewmodel1"/>
    
    
          <ResourceDictionary x:Key="RD1">
             <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/PropertyPages/StandardMapGeneralTemplate.xaml"/>
             </ResourceDictionary.MergedDictionaries>
          </ResourceDictionary>
       </UserControl.Resources>
    

    Any ideas?

    Tuesday, December 15, 2015 3:04 PM
  • I would usually just merge in all resource dictionaries in app.xaml.

    The order you have the stuff defined in can matter.

    Sometimes you need to have the thing you're going to base on merged in first or defined in the same rd first.

    But basically, if it works on one place it _can_ still work somewhere else.

    So long as you get the right combination of circumstances.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Tuesday, December 15, 2015 3:40 PM
    Moderator