EmptyListToVisibilityConverter
I'm trying to do an "empty list to visibility converter" for WPF. This is an IValueConverter that takes an object ( that should be a list ) and if the list is empty (or if the passed object is null ) it should return Visibility.Collapsed; if the list is not empty it should return Visibility.Visibile;
I plan to use this for a datagrid. The plan is to make the datagrid invisible (collapsed) whenever the list given to the ItemsSource is an empty list or a null.
<my:DataGrid
Name="dataGridAuxiliaryTools"
开发者_如何学Go Style="{StaticResource DataGridStyle}"
CellStyle="{StaticResource DataGridCellStyle}"
ColumnHeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
ItemsSource="{Binding Path=Items}"
IsReadOnly="False"
Visibility="{Binding Path=Items,
Converter={StaticResource emptyListToVisibilityConverter}}"
</my:DataGrid>
I wrote the EmptyListToVisibilityConverter as follows:
public class EmptyListToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
if (value == null)
{
return Visibility.Collapsed;
}
else if (value is IList<Object>)
{
if ((value as IList<Object>).Count == 0)
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
else
{
return Visibility.Visible;
}
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
This works well when Items is given as null but when Items is given as a List it does not work ... I think that the code bellow is not correct and cannot detect if "value" is a list or not ... Any hints ?
if (value is IList<Object>)
{
if ((value as IList<Object>).Count == 0)
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
Any hints on how to do this ?
You can't cast your list to IList <Object>, but you can cast it to ICollection, and then use ICollection.Count : see http://devw.wordpress.com/2011/07/18/empty-list-visibility-converter/
public class EmptyListVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
else
{
ICollection list = value as ICollection;
if (list != null)
{
if (list.Count == 0)
return Visibility.Collapsed;
else
return Visibility.Visible;
}
else
return Visibility.Visible;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
<ListBox x:Name=”NameChoiceListBox”
ItemsSource=”{Binding NamesList}”
SelectedItem=”{Binding SelectedName, Mode=TwoWay}”
ItemTemplate=”{StaticResource DataTemplateNameChoice}”
Visibility=”{Binding NamesList, Converter={StaticResource EmptyListVisibilityConverter}}”>
I guess the problem is, that the collection object stays the same, when you add or remove items from it. So the binding does not update the value and the converter is not called.
I think its quite straight forward, here you go:
public class NullOrEmptyCollectionToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return Visibility.Collapsed;
var collection = value as ICollection;
return collection != null ? (collection.Count == 0 ? Visibility.Collapsed : Visibility.Visible) : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Hoping wil help, thanks! - Shams
My guess is that it's because of the fact that you're using IList<Object>
in the converter but your actual collection is an IList<SomethingElse>
. See, IList is not covariant so you can't just convert any IList<T>
to an IList<Object>
. My suggestion will be to try and use IEnumerable<object>
in the converter instead and use the Count() extension method to determine the number of items in the collection.
C# version 7 supports pattern matching. Now you can write:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch (value)
{
case null:
return Visibility.Collapsed;
case ICollection list:
return list.Count == 0 ? Visibility.Collapsed : Visibility.Visible;
}
return Visibility.Visible;
}
A better alternative is to use ObservableCollection and then bind to its Count property: WPF Converters and ObservableCollections
精彩评论