Empty message on ItemsControl when binding List<T> is empty!
I am seeking for a way to show a message No records found
instead of a the ItemsControl that is rending my List<T>
when my list.Count == 0
!
I did this once in WPF using DataTemplateSelector
, but it seems that Silverlight doesn't support this!
It would be nice to have this UI logic in XAML instead of backend
or my ViewModel
which is comparati开发者_JS百科vely easy!
TIA
DelwarYou can bind the Visibility
property of the ItemsControl
to the source list using a custom IValueConverter
; inside the IValueConverter
you can return Visibility.Visible
or Visibility.Collapsed
according to the number of items into the source collection.
The same goes, with a converter using an opposite logic, for a TextBlock
containing the "No items" message.
I can't figure how to solve the empty list problem with DataTemplateSelector
, since the Empty template will not be applied anyway.
Yet, you can achieve quite the same behaviour of DataTemplateSelector
using an IValueConverter
to bind the list to the DataTemplate
property.
Using this solution, however, makes difficult to return a DataTemplate
defined in the control Xaml; you can use a template stored into applicatior resources, though.
Does it help?
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)
精彩评论