Search code examples
c#wpfxamllistboxitemcontainerstyle

How to define a style for a listbox depending upon the collection?


I want to change a style of a listbox depending upon the collection I am using. In my code, the first class has a collection of TypeAItemViewModel. The collection will has 1 item that cannot be selected (assume as a header), and for that I will use IsHitTestVisible.

But the other class uses a collection of NormalParameters that has no IsHitTestVisible. Then, when I use a view with a NormalParameter collection it gives me an error with no IsHitTestVisible property.

public List<NormalParameters> Items{get;set;}
public List<TypeAItemViewModel> Items;

Class: TypeAItemViewModel

public class TypeAItemViewModel
{
    private TypeAParameter _parameter;      
    public bool IsHitTestVisible{get;set;}
}

style:

<Style x:Key="SelectableListBoxItem" TargetType="{x:Type ListBoxItem}">
    <Setter Property="IsHitTestVisible" Value="{Binding IsHitTestVisible}" />   
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsHitTestVisible}" Value="false">
            <Setter Property="FontWeight" Value="SemiBold" />
            <Setter Property="FontSize" Value="{StaticResource FontSizeTextBlock}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

Listbox: (work fines with collection of TypeAItemViewModel)

<ListBox HorizontalContentAlignment="Stretch" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" ItemContainerStyle="{DynamicResource SelectableListBoxItem}">
    <ListBox.ItemTemplate>                    
        <DataTemplate>
            <Grid Height="{StaticResource Height}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="100" />
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="0">
                    <TextBlock DataContext="{Binding Name}" Text="{Binding Value}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

I thought it should to work with ItemContainerStyle but I still cannot solve it.

if unclear, please let me know.

edit: I have 2 collections. I want to display them different style with 1 xaml listbox. edit: Listbox that I use is a usercontrol


Solution

  • @Valera thank you so much. your answer is a very healthy food for my problem.

    I have added a new boolean property then use it to define which style I want to use.

    <Style x:Key="ListBoxWithIsHitTestVisible" TargetType="{x:Type ListBox}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsListBoxWithHeaderItem}" Value="true">
                <Setter Property="ItemContainerStyle" Value="{DynamicResource SelectableListBoxItem}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    
    <Style x:Key="SelectableListBoxItem" TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsHitTestVisible" Value="{Binding IsHitTestVisible}" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsHitTestVisible}" Value="false">
                <Setter Property="FontWeight" Value="SemiBold" />
                <Setter Property="FontSize" Value="{StaticResource FontSizeTextBlock}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    

    and this is a listbox xaml code

    <ListBox Grid.Row="1" HorizontalContentAlignment="Stretch" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" Style="{StaticResource ListBoxWithIsHitTestVisible}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Height="{StaticResource Height}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="100" />
                    </Grid.ColumnDefinitions>
                    <Grid Grid.Column="0">
                        <TextBlock DataContext="{Binding Name}" Text="{Binding Value}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    </Grid>
                </Grid>
            </DataTemplate>                    
        </ListBox.ItemTemplate>
    </ListBox>