我有一个字符串的 ObservableCollection:
public ObservableCollection<string> ChallengePartImageURLs { get; } = new ObservableCollection<string>();
像这样填充/更新:
ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
ChallengePartImageURLs.Add(url);
}
UI 更新得很好,但是当集合发生变化时,转换器不会被触发:
IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}"
转换器正在工作,因为如果我将 ObservableCollection 更改为 ObservableProperty,它就会被完美触发。
我已尝试将 Binding 包含到 ObservableProperty 的 ConverterParameter 中,但仍然没有触发。
我是否遗漏了什么或者有没有办法触发转换器?
更新
该转换器在 XAML 中声明:
<ContentPage.Resources>
<ResourceDictionary>
<converters:AnyImageCheckConverter x:Key="AnyImageCheckConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
用过的:
<CollectionView ItemsSource="{Binding ChallengePartImageURLs}" IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
转换器本身:
{
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();
}
}
仅通过清除收藏品并添加新物品才能更改收藏品。
您发现,转换器未触发的主要原因是转换器仅在 PropertyChangedEvent 之后运行。当清除、添加或删除项目时,ObservableCollection 会发出NotifyCollectionChangedAction。
对于您的用例而言,这实际上意味着触发属性更改事件,以便在您更新集合后运行转换器。这种行为方式的好处在于,您的页面不会在每次从集合中添加或删除内容时运行转换器。
或者如果你使用MVVM 工具包,你可以简化 propteryChanged 调用
希望这对您有所帮助。我曾多次在我的应用中实现这种行为。我发现扩展 ObservableCollection 以添加此行为非常有益。
作为更迂回的替代方案
IValueConverter
,这种事情可以在 ViewModel 中干净利落地实现,例如通过添加 forbool
和AnyImageUrl
处理CollectionChanged
。最小示例