locked
style not applied in ListBox.ItemTemplate RRS feed

  • Question

  • I have a resource dictionary with a style for Borders. The style has a TargetType but no x:Key. The dictionary also has a DataTemplate used as a ListBox.ItemTemplate. The DataTemplate has a Border in it. The Border style is not applied in the ListBox. I assumed that it would be. That is what I want.

    What is the simplest way to get the Border style applied in the ListBox.ItemTemplate?

    Bill

    Wednesday, September 22, 2010 8:37 PM

Answers

  • Hi Bill,

    I made a small sample for this issue as follow.

        <Window.Resources>

            <Style TargetType="{x:Type Border}">

                <Setter Property="Background" Value="Green"/>

            </Style>

            <Style TargetType="{x:Type TextBlock}">

                <Setter Property="Foreground" Value="Yellow"/>

            </Style>

        </Window.Resources>

        <StackPanel>

            <!--Attempt1-->

            <Border Height="30">

                <TextBlock>Attempt1</TextBlock>

            </Border>

            <!--Attempt2-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <Border Height="30">

                            <TextBlock>Attempt2</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

            <!--Attempt3-->

            <ListBox ItemsSource="{Binding}">

                <ListBox.ItemTemplate>

                    <DataTemplate>

                        <Border Height="30">

                            <TextBlock>Attempt3</TextBlock>

                        </Border>

                    </DataTemplate>

                </ListBox.ItemTemplate>

            </ListBox>

            <!--Attempt4-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <DataTemplate.Resources>

                            <Style TargetType="{x:Type Border}">

                                <Setter Property="Background" Value="Green"/>

                            </Style>

                            <Style TargetType="{x:Type TextBlock}">

                                <Setter Property="Foreground" Value="Yellow"/>

                            </Style>

                        </DataTemplate.Resources>

                        <Border Height="30">

                            <TextBlock>Attempt4</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

            <!--Attempt5-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <Border Style="{StaticResource {x:Type Border}}" Height="30">

                            <TextBlock Style="{StaticResource {x:Type TextBlock}}">Attempt5</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

        </StackPanel>

     

    C# code:

            public Window1()

            {

                InitializeComponent();

                this.DataContext = new string[1]{""};

            }

     

    Descriptions:

    Attempt 1: A typed style is working outside a DataTemplate.

    Attempt 2: A typed style is not working inside a DataTemplate.

    Attempt 4: It’s working if it is defined in DataTemplate.Resources.

    Attempt 5: It’s working if it is explicitly asked to find the corresponding typed style.

    Also, all of Attempt 1-5 will work if I change the Borders to Buttons.

    And Attempt 6:  If these implicit styles are defined at Application level, they will be applied to non-control elements in a DataTemplate.

    The result indicates that typed styles will not be applied to non-control elements in a DataTemplate or control Template. I suspect this behavior is by design. It makes sense not to apply implicit styles to non-control elements, because if it does, it might have an unexpected impact on other controls. However, I cannot find any documentation about this behavior.

    You can see a similar discussion at http://blogs.msdn.com/b/wpfsdk/archive/2009/08/27/implicit-styles-templates-controls-and-frameworkelements.aspx.

    To work around your current issue,please try Attempt 5 or Attempt4. It should be able to solve this issue in most cases. Please feel free to let me know if for some reason it doesn't solve your issue.

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • Marked as answer by Bill Swartz Wednesday, September 29, 2010 6:04 PM
    Wednesday, September 29, 2010 1:55 AM

All replies

  • Sounds like it should work. Can you post up some code?
    If my response answers your question, please mark it as the "Answer" by clicking that button above my post.

    My blog: http://www.RyanVice.net/
    Wednesday, September 22, 2010 8:42 PM
  • The code is part of a larger project. I will make a simpler test project and post it.

    Bill

    Thursday, September 23, 2010 4:02 PM
  • I have created a simple demo. The 2 items in the ListBox don't use the Style to display their Borders.

    Here is some xaml:

    <Window x:Class="ItemTemplateStyle.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:ItemTemplateStyle"
      Title="Window1" Height="300" Width="300">
      <Window.Resources>
        <local:People x:Key="people" />
        <Style TargetType="Border">
          <Setter Property="BorderThickness" Value="3" />
          <Setter Property="CornerRadius" Value="6" />
          <Setter Property="Margin" Value="6" />
          <Setter Property="BorderBrush" Value="LightBlue" />
        </Style>
      </Window.Resources>
      <Grid>
        <Border>
          <ListBox
            Height="100" HorizontalAlignment="Center" VerticalAlignment="Center"
            Width="100" ItemsSource="{Binding Source={StaticResource people}}"
            >
            <ListBox.ItemTemplate>
              <DataTemplate DataType="local:Person">
                <Border>
                  <Grid Margin="3">
                    <Grid.RowDefinitions>
                      <RowDefinition />
                      <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="0" Text="{Binding Path=First}" />
                    <TextBlock Grid.Row="1" Text="{Binding Path=Last}" />
                  </Grid>
                </Border>
              </DataTemplate>
            </ListBox.ItemTemplate>
          </ListBox>
        </Border>
      </Grid>
    </Window>
    
    

    Here is the code-behind:

    using System;
    using System.Windows;
    using System.Collections.ObjectModel;
    
    namespace ItemTemplateStyle
    {
      /// <summary>
      /// Interaction logic for Window1.xaml
      /// </summary>
      public partial class Window1 : Window
      {
        [STAThread]
        public static void Main()
        {
          Application app = new Application();
          app.Run(new Window1());
        }
    
        public Window1()
        {
          InitializeComponent();
        }
      }
    
      public class Person
      {
        public string First { get; set; }
        public string Last { get; set; }
    
        public Person(string first, string last)
        {
          First = first;
          Last = last;
        }
      }
    
      public class People
        : ObservableCollection<Person>
      {
        public People()
          : base()
        {
          Add(new Person("Humpty","Dumpty"));
          Add(new Person("Howdy","Doody"));
        }
      }
    }
    
    

    Thursday, September 23, 2010 8:37 PM
  • hi,

     

    i think you should use Style like this.

    <Style TargetType="{x:Type Border}">

    instead of simple TargetType = "Border"

     

    Regards,

    Suhas Joyous

    Friday, September 24, 2010 1:47 PM
  • I tried the change to TargetType. It made no difference.

    Bill

    Friday, September 24, 2010 3:01 PM
  • This works. There were a few problems with yours. First is that you have the wrong syntax for TargetType, it should be

    TargetType="{x:Type Border}"
    

    Second is that you have two borders at play. I used a control template to set the border as I couldn't figure out how to set it using just a style and applying that to the list box. End of the day it works but there may be a simpler way of doing this.

    <Window x:Class="WpfForumSandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfForumSandbox"
        Title="MainWindow" Height="350" Width="525">
      <Window.Resources>
        <local:People x:Key="people" />
        <Style TargetType="{x:Type ListBox}">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate>
                <Border BorderThickness="3" CornerRadius="6" Margin="6" BorderBrush="LightBlue">
                  <ScrollViewer 
                    Padding="{TemplateBinding Padding}" 
                    Background="{TemplateBinding Background}" 
                    BorderThickness="0" 
                    TabIndex="{TemplateBinding TabIndex}">
                    <StackPanel>
                      <ItemsPresenter/>
                    </StackPanel>
                  </ScrollViewer>
                </Border>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </Window.Resources>
      <Grid>
        <ListBox
          HorizontalAlignment="Center" VerticalAlignment="Center"
          ItemsSource="{Binding Source={StaticResource people}}"
          Margin="5"
          >
          <ListBox.ItemTemplate>
            <DataTemplate DataType="local:Person">
              <Border>
                <Grid Margin="3">
                  <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                  </Grid.RowDefinitions>
                  <TextBlock Grid.Row="0" Text="{Binding Path=First}" />
                  <TextBlock Grid.Row="1" Text="{Binding Path=Last}" />
                </Grid>
              </Border>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </Window>
    

    If my response answers your question, please mark it as the "Answer" by clicking that button above my post.

    My blog: http://www.RyanVice.net/
    • Proposed as answer by Ryan Vice Friday, September 24, 2010 3:29 PM
    Friday, September 24, 2010 3:29 PM
  • You directly applied properties to the Border in the template. For purposes of software maintainability, I am trying to avoid doing that.

    Bill

    Friday, September 24, 2010 3:54 PM
  • Apparently, the simplest thing is to give the Style an x:Key attribute, then apply the Style with 'Style="{StaticResource ...}"'.

    Bill

    Friday, September 24, 2010 7:03 PM
  • You directly applied properties to the Border in the template. For purposes of software maintainability, I am trying to avoid doing that.

    Bill


    No I didn't, the values are applied in the style via a control template not directly to the control and I don't see any maintance problem with using a style to apply styling but please elaborate if I'm missing something.


    If my response answers your question, please mark it as the "Answer" by clicking that button above my post.

    My blog: http://www.RyanVice.net/
    Friday, September 24, 2010 7:49 PM
  • Hi Bill,

    I made a small sample for this issue as follow.

        <Window.Resources>

            <Style TargetType="{x:Type Border}">

                <Setter Property="Background" Value="Green"/>

            </Style>

            <Style TargetType="{x:Type TextBlock}">

                <Setter Property="Foreground" Value="Yellow"/>

            </Style>

        </Window.Resources>

        <StackPanel>

            <!--Attempt1-->

            <Border Height="30">

                <TextBlock>Attempt1</TextBlock>

            </Border>

            <!--Attempt2-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <Border Height="30">

                            <TextBlock>Attempt2</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

            <!--Attempt3-->

            <ListBox ItemsSource="{Binding}">

                <ListBox.ItemTemplate>

                    <DataTemplate>

                        <Border Height="30">

                            <TextBlock>Attempt3</TextBlock>

                        </Border>

                    </DataTemplate>

                </ListBox.ItemTemplate>

            </ListBox>

            <!--Attempt4-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <DataTemplate.Resources>

                            <Style TargetType="{x:Type Border}">

                                <Setter Property="Background" Value="Green"/>

                            </Style>

                            <Style TargetType="{x:Type TextBlock}">

                                <Setter Property="Foreground" Value="Yellow"/>

                            </Style>

                        </DataTemplate.Resources>

                        <Border Height="30">

                            <TextBlock>Attempt4</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

            <!--Attempt5-->

            <ContentPresenter>

                <ContentPresenter.ContentTemplate>

                    <DataTemplate>

                        <Border Style="{StaticResource {x:Type Border}}" Height="30">

                            <TextBlock Style="{StaticResource {x:Type TextBlock}}">Attempt5</TextBlock>

                        </Border>

                    </DataTemplate>

                </ContentPresenter.ContentTemplate>

            </ContentPresenter>

        </StackPanel>

     

    C# code:

            public Window1()

            {

                InitializeComponent();

                this.DataContext = new string[1]{""};

            }

     

    Descriptions:

    Attempt 1: A typed style is working outside a DataTemplate.

    Attempt 2: A typed style is not working inside a DataTemplate.

    Attempt 4: It’s working if it is defined in DataTemplate.Resources.

    Attempt 5: It’s working if it is explicitly asked to find the corresponding typed style.

    Also, all of Attempt 1-5 will work if I change the Borders to Buttons.

    And Attempt 6:  If these implicit styles are defined at Application level, they will be applied to non-control elements in a DataTemplate.

    The result indicates that typed styles will not be applied to non-control elements in a DataTemplate or control Template. I suspect this behavior is by design. It makes sense not to apply implicit styles to non-control elements, because if it does, it might have an unexpected impact on other controls. However, I cannot find any documentation about this behavior.

    You can see a similar discussion at http://blogs.msdn.com/b/wpfsdk/archive/2009/08/27/implicit-styles-templates-controls-and-frameworkelements.aspx.

    To work around your current issue,please try Attempt 5 or Attempt4. It should be able to solve this issue in most cases. Please feel free to let me know if for some reason it doesn't solve your issue.

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • Marked as answer by Bill Swartz Wednesday, September 29, 2010 6:04 PM
    Wednesday, September 29, 2010 1:55 AM