I have an ObservableCollection of strings:
public ObservableCollection<string> ChallengePartImageURLs { get; } = new ObservableCollection<string>();
Being populated/updated like this:
ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
ChallengePartImageURLs.Add(url);
}
The UI is updated just fine, however, the converter is not triggered when the collection is changing:
IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}"
The converter is working because if I change the ObservableCollection to an ObservableProperty it is perfectly triggered.
I have tried including a Binding to a ConverterParameter of an ObservableProperty but it is still not triggered.
Am I missing something or is there a way to trigger the converter?
Update
The converter is declared in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<converters:AnyImageCheckConverter x:Key="AnyImageCheckConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
Used:
<CollectionView ItemsSource="{Binding ChallengePartImageURLs}" IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The converter itself:
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value != null)
{
var list = (ObservableCollection<string>)value;
if (list.Count > 0)
{
return true;
}
else
{
return false;
}
}
return false;
}
catch (Exception ex)
{
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The Collection is only changed by clearing it and adding new items.
I have an ObservableCollection of strings:
public ObservableCollection<string> ChallengePartImageURLs { get; } = new ObservableCollection<string>();
Being populated/updated like this:
ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
ChallengePartImageURLs.Add(url);
}
The UI is updated just fine, however, the converter is not triggered when the collection is changing:
IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}"
The converter is working because if I change the ObservableCollection to an ObservableProperty it is perfectly triggered.
I have tried including a Binding to a ConverterParameter of an ObservableProperty but it is still not triggered.
Am I missing something or is there a way to trigger the converter?
Update
The converter is declared in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<converters:AnyImageCheckConverter x:Key="AnyImageCheckConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
Used:
<CollectionView ItemsSource="{Binding ChallengePartImageURLs}" IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The converter itself:
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value != null)
{
var list = (ObservableCollection<string>)value;
if (list.Count > 0)
{
return true;
}
else
{
return false;
}
}
return false;
}
catch (Exception ex)
{
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The Collection is only changed by clearing it and adding new items.
Share Improve this question edited Jan 22 at 16:34 Kasper Sommer asked Jan 22 at 16:13 Kasper SommerKasper Sommer 4631 gold badge8 silver badges20 bronze badges 2- please provide some more context - the small snipped you posted does not show us how/where the converter is attached. And please be more specific what you mean by "changing" the collection - are you adding/removing elements? Changing an existing element? Reassigning the entire collection? – Jason Commented Jan 22 at 16:17
- Please show how did you declare the converter in your xaml. – Rafael Commented Jan 22 at 16:20
1 Answer
Reset to default 2The main reason that the converter is not triggered, as you discovered, is that the Converter will only be run after a PropertyChangedEvent. The ObservableCollection when items are cleared, added, or removed emit NotifyCollectionChangedAction.
What that means practically for your use case is to trigger a property changed event so that the converter will be run after you update the collection. The nice part about the way this behaves is that your page will not run the converter each time something is added or removed from you collection.
ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
ChallengePartImageURLs.Add(url);
}
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ChallengePartImageURLs)));
Or if you are using MVVM toolkit, you can simplify the propteryChanged call
ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
ChallengePartImageURLs.Add(url);
}
OnPropertyChanged(nameof(ChallengePartImageURLs));
I hope you find this helpful. I have had to implement this kind of behavior numerous times in my app. I found extending ObservableCollection to add this behavior quite beneficial.