WPF listbox empty datatemplate
Asked Answered
S

2

55

I was wondering how people handle a ListBox control that has no items? e.g. I want to bind a list of search results but if no results are found i would like to display "No results found".

The way i currently tackle this is that i hide the listbox if the result set count = 0 and show a label with the "No results found" message. Ideally i would like something like the ASP .NET datagrid EmptyTemplate solution.

Cheers

Secretion answered 31/3, 2009 at 3:11 Comment(0)
C
110

I've had some success with this code:

<Style TargetType="ListBox" x:Key="ListStyle" BasedOn="{StaticResource {x:Type ListBox}}">
    <Style.Triggers>
        <DataTrigger 
            Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Items.Count}" 
            Value="0"
            >
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBlock>No items to display</TextBlock>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
Composed answered 31/3, 2009 at 3:16 Comment(6)
I saw variants with data template selectors, but this one is without code-behind, brilliant!Acetometer
I just copy pasted it to clean new application and it doesn't work. I set listBox.ItemsSource = new List<string>() and nothing is displayed.Syllabify
Ok, if you want it to work for every ListBox, remove the x:Key="ListStyle". Otherwise each ListBox has to specify that it uses this concrete named style.Syllabify
Hey guys, is there a silverlight variation for this?Aristocracy
It works, but it raises a problem for me. My listbox accepts drop into it (drag-and-drop), however when I set that Template it can no longer accept drops, only when I mouse over the actual content, that is, the TextBlock. How can I solve this?Undergraduate
@Undergraduate open a new question with that.Jewess
D
24

Based on @Matt Hamilton's accepted answer, for reference, I created a variation which does not require the binding, as it uses the HasItems property of the ListBox to trigger the empty template:

<ListBox.Style>
    <Style x:Key="EmptyListStyle"
           TargetType="ListBox"
           BasedOn="{StaticResource {x:Type ListBox}}">
        <Style.Triggers>
            <!-- Use ListBox.HasItems instead of Binding -->
            <Trigger Property="HasItems" Value="False">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <TextBlock>No items to display</TextBlock>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</ListBox.Style>

This allows the style to be used globally, without having to know the property name to which the list binds. I found it useful when binding to a CollectionViewSource defined in XAML.

I'm not aware of any drawbacks of this method, comments welcome if you should find any.

Decembrist answered 22/2, 2016 at 11:49 Comment(5)
It works, but it raises a problem for me. My listbox accepts drop into it (drag-and-drop), however when I set that Template it can no longer accept drops, only when I mouse over the actual content, that is, the TextBlock. How can I solve this?Undergraduate
It's possible that the drag-drop behavior comes from the ListBoxItems rather than the ListBox itself. Perhaps adding the TextBlock to a ListBoxItem in the control template might get round this problem? I'd recommend taking a look at the WPF reference sources and working with Snoop too.Decembrist
I'm using WPF Inspector and I have tried to add the TextBlock inside a ListBoxItem, however the problem remains... when I Horizontal & Vertical align the content to center (so the text is shown on the center of ListBox)Undergraduate
OK... I'd suggest you post a question separately then, where you can provide more details.Decembrist
The drag/drop thing may be because there's no background set on the control template. (TextBlock's defaults to null). To get around that, put the TextBlock in a Border and set its background to Transparent. That will make it visible again to the mouse.Stockman

© 2022 - 2024 — McMap. All rights reserved.