views:

310

answers:

1

I’m trying to bind a List of items to a listbox in WPF. The items are grouped by one value and each group is to be housed in an expander. Everything works fine when I don’t use any custom styles. However, when I use custom styles (which work properly with non-grouped items and as independent controls) the binding doesn’t display any items. Below is the code I’m executing. Any ideas why the items won’t show up in the Expander?

Test.xaml:

<Window x:Class="Glossy.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="300" Width="300">

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="..\TestStyles.xaml"/>

            <ResourceDictionary>
                <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Expander Header="{Binding}" IsExpanded="True">
                                    <ItemsPresenter />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ResourceDictionary>

        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary> 
</Window.Resources>



<Grid>        
    <ListBox x:Name="TestList">
        <ListBox.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
        </ListBox.GroupStyle>
    </ListBox>
</Grid>

Test.xaml.cs:

public partial class Test : Window
{
    private List<Contact> _ContactItems;
    public List<Contact> ContactItems
    {
        get { return _ContactItems; }
        set { _ContactItems = value; }
    }



    public Test()
    {
        InitializeComponent();

        ContactItems = new List<Contact>();
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 1";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 2";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 3";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 10";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 11";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "ABC";
        ContactItems.Last().Name = "Contact 12";

        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "RST";
        ContactItems.Last().Name = "Contact 7";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "RST";
        ContactItems.Last().Name = "Contact 8";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "RST";
        ContactItems.Last().Name = "Contact 9";

        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "XYZ";
        ContactItems.Last().Name = "Contact 4";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "XYZ";
        ContactItems.Last().Name = "Contact 5";
        ContactItems.Add(new Contact());
        ContactItems.Last().CompanyName = "XYZ";
        ContactItems.Last().Name = "Contact 6";



        ICollectionView view = CollectionViewSource.GetDefaultView(ContactItems);
        view.GroupDescriptions.Add(new PropertyGroupDescription("CompanyName"));
        view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
        TestList.ItemsSource = view;
    }
}



public class Contact
{
    public string CompanyName { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

TestStyles.xaml:

<Style TargetType="{x:Type ListBox}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="MinWidth" Value="120"/>
    <Setter Property="MinHeight" Value="95"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBox">
                <Grid Background="Black">
                    <Rectangle VerticalAlignment="Stretch"
                                               HorizontalAlignment="Stretch"
                                               Fill="White">
                        <Rectangle.OpacityMask>
                            <DrawingBrush>
                                <DrawingBrush.Drawing>
                                    <GeometryDrawing Geometry="M65.5,33 L537.5,35 537.5,274.5 C536.5,81 119.5,177 66.5,92" Brush="#11444444">
                                        <GeometryDrawing.Pen>
                                            <Pen Brush="Transparent"/>
                                        </GeometryDrawing.Pen>
                                    </GeometryDrawing>
                                </DrawingBrush.Drawing>
                            </DrawingBrush>
                        </Rectangle.OpacityMask>
                    </Rectangle>
                    <Border Name="Border"
                                            Background="Transparent"
                                            BorderBrush="Gray"
                                            BorderThickness="1"
                                            CornerRadius="2">
                        <ScrollViewer Margin="0" Focusable="false">
                            <StackPanel Margin="2" IsItemsHost="True" />
                        </ScrollViewer>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="Border" Property="Background" Value="Gray" />
                        <Setter TargetName="Border" Property="BorderBrush" Value="DimGray" />
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="Foreground" Value="Gray"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="FontFamily" Value="Verdana"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="FontSize" Value="11"/>
    <Setter Property="Margin" Value="3,1,3,1"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Border Name="Border"
                                        Padding="2"
                                        SnapsToDevicePixels="true">
                    <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Border" Property="Background" Value="Gray"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="White"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="ExpanderToggleButton" TargetType="ToggleButton">
    <Border Name="Border" 
                            CornerRadius="2,0,0,0"
                            Background="Transparent"
                            BorderBrush="LightGray"
                            BorderThickness="0,0,1,0">
        <Path Name="Arrow"
                              Fill="Blue"
                              HorizontalAlignment="Center"
                              VerticalAlignment="Center"
                              Data="M 0 0 L 4 4 L 8 0 Z"/>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="ToggleButton.IsMouseOver" Value="True">
            <Setter TargetName="Border" Property="Background" Value="Gray" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="Border" Property="Background" Value="Black" />
        </Trigger>
        <Trigger Property="IsChecked" Value="True">
            <Setter TargetName="Arrow" Property="Data" Value="M 0 4 L 4 0 L 8 4 Z" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter TargetName="Border" Property="Background" Value="DimGray" />
            <Setter TargetName="Border" Property="BorderBrush" Value="DimGray" />
            <Setter Property="Foreground" Value="LightGray"/>
            <Setter TargetName="Arrow" Property="Fill" Value="LightBlue" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style TargetType="{x:Type Expander}">
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="FontFamily" Value="Verdana"/>
    <Setter Property="FontSize" Value="11"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Expander">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Name="ContentRow" Height="0"/>
                    </Grid.RowDefinitions>
                    <Border Name="Border" 
                                            Grid.Row="0" 
                                            Background="Black"
                                            BorderBrush="DimGray"
                                            BorderThickness="1" 
                                            Cursor="Hand"
                                            CornerRadius="2,2,0,0" >
                        <Grid HorizontalAlignment="Left">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="23"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="20" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <ToggleButton IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                                                          Template="{StaticResource ExpanderToggleButton}" 
                                                          Background="Black" />
                            <Label Grid.Column="1"
                                                   FontSize="14"
                                                   FontWeight="Normal"
                                                   Margin="0"
                                                   VerticalAlignment="Top"
                                                   Foreground="White"
                                                   FontFamily="Verdana">
                                <ContentPresenter Grid.Column="1"
                                                                  Margin="4,3,0,0" 
                                                                  HorizontalAlignment="Left"
                                                                  ContentSource="Header" 
                                                                  RecognizesAccessKey="True" />
                            </Label>
                        </Grid>
                    </Border>
                    <Border Name="Content"                                  
                                            Background="Black"
                                            BorderBrush="DimGray" 
                                            BorderThickness="1,0,1,1" 
                                            Grid.Row="1"
                                            CornerRadius="0,0,2,2" >
                        <Grid  Background="Black">
                            <Rectangle VerticalAlignment="Stretch"
                                                        HorizontalAlignment="Stretch"
                                                        Fill="White">
                                <Rectangle.OpacityMask>
                                    <DrawingBrush>
                                        <DrawingBrush.Drawing>
                                            <GeometryDrawing Geometry="M65.5,33 L537.5,35 537.5,274.5 C536.5,81 119.5,177 66.5,92" Brush="#11444444">
                                                <GeometryDrawing.Pen>
                                                    <Pen Brush="Transparent"/>
                                                </GeometryDrawing.Pen>
                                            </GeometryDrawing>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Rectangle.OpacityMask>
                            </Rectangle>
                            <ContentPresenter Margin="4" />
                        </Grid>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="True">
                        <Setter TargetName="ContentRow" Property="Height" Value="{Binding ElementName=Content,Path=DesiredHeight}" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="Border" Property="Background" Value="Gray" />
                        <Setter TargetName="Border" Property="BorderBrush" Value="DimGray" />
                        <Setter Property="Foreground" Value="White"/>
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

+1  A: 

Use an ItemsPresenter instead of the StackPanel in your ListBox control template (in TestStyles.xaml).

Thanks, that did the trick!