gurehbgui
gurehbgui

Reputation: 14694

Setting default text when a ListBox contains no elements

Is it possible to use some form of default text for a ListBox when it contains no elements?

e.g. When i dont have items in the list i want to show the following text: please add some items

Upvotes: 1

Views: 728

Answers (2)

Mike S.
Mike S.

Reputation: 502

I've come up with a simple solution for listboxes that works for me in 99% of the cases. Once setup as a resource, all you have to do is change the Tag property on the listbox to get all the functionality to work.

First, I modify the default template of the Listbox to include a new grid and a textbox like so:

Original XAML

<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" Margin="0">
    <ScrollViewer x:Name="ScrollViewer" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Margin="0" Padding="0" TabNavigation="{TemplateBinding TabNavigation}">
        <ItemsPresenter Margin="0,0" />
    </ScrollViewer>
</Border>

New XAML

<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" Margin="0">
    <Grid >
        <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemsSource.Count, Converter={StaticResource ListCount2Visibility}}" Foreground="{StaticResource NormalFontBrush}" FontSize="{StaticResource DefaultFontSize}" />

        <ScrollViewer x:Name="ScrollViewer" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Margin="0" Padding="0" TabNavigation="{TemplateBinding TabNavigation}">
            <ItemsPresenter Margin="0,0" />
        </ScrollViewer>
    </Grid>
</Border>

The textblock visibility property is bound to a custom converter entitled ListCount2Visibility which looks like this:

public sealed class ListCount2Visibility : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null && (int)value > 0 )
            return "Collapsed";
        else
            return "Visible";

    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The value converter checks if the ItemSource.Count == 0...if it is, it sets the visibility to visible. Otherwise, it collapses it.

The Text property of the new textblock is then bound to the Tag property of the listbox. (This isn't ideal but it is the quickest way to get the text into the control. Obviously this won't work if you use the tag property for other things).

So basically, you set the tag to the message you want to display, and anytime there are no items in the list, the textbox is shown (centered horizontally and vertically). During development, your message will show since the list is empty (assuming now design time datacontext) which makes it nice to visualize the text.

That is really all there is to it.

If you want, you can even bind the tag property of the listbox to your viewmodel to change the text. So you could do things like "loading...." while items are returned from the database and then change it to the "empty list" message after everything loads. (of course busy indicator is probably better)

Upvotes: 0

Filip Skakun
Filip Skakun

Reputation: 31724

You would typically need to handle it yourself - overlay the ListBox with your message and make the message visible when there are no items to display. You could bind the message UI's visibility to the same source as the ListBox's ItemsSource and use a converter to return Visibility.Visible when ItemsSource is null. I don't think that will work with the actual collection being null, so for that - you can either handle the collection items count changes wherever you prefer (code behind/view model) and adjust the visibility of the overlay or implement a reusable attached property/behavior/control.

Upvotes: 3

Related Questions