为什么 IMultiValueConverter 没有将更新的 ObservableCollection 作为参数获取?
Why IMultiValueConverter doesn't get updated ObservableCollection as a parameter?
我有一个 ItemsControl
是这样设置的:
<ItemsControl ItemsSource="{Binding GameObjects}"
AlternationCount="{Binding GameObjects.Count}"
Grid.RowSpan="10"
Grid.ColumnSpan="10">
<DataTemplate>
<Grid>
<Grid.DataContext>
<vm:MainWindowViewModel/>
</Grid.DataContext>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource TemplatedParent}}"/>
<Image>
<Image.Source>
<MultiBinding Converter="{StaticResource
ObservableCollectionItemByAlternationIndex}">
<Binding Path="Textures"/>
<Binding Path="GameObjects"/>
<Binding Path="(ItemsControl.AlternationIndex)"
RelativeSource="{RelativeSource TemplatedParent}"/>
</MultiBinding>
</Image.Source>
</Image>
</Grid>
</DataTemplate>
转换器如下所示:
public override object Convert(object[] v, Type t, object p, CultureInfo c)
{
var value1 = (ObservableCollection<string>)v[0];
var value2 = (ObservableCollection<GameObject>)v[1];
var value3 = (int)v[2];
foreach(var tex in value1)
{
if ("/Maelstrom;component//Data/Resources/Textures/" + value2[value3].GetType().Name + ".png" == tex)
{
return new BitmapImage(new Uri("pack://application:,,," + tex));
}
}
return new BitmapImage(new Uri("pack://application:,,," + value1[0]));
}
这里的问题是,当我更新 GameObjects
时,转换器不会获取 GameObjects
的更新版本,value1
将包含 value1
中的所有元素=14=] 程序启动时。 ItemsControl
更新正常(从 GameObjects
中删除的项目也从 UI 中删除)。
问题是您混淆了 INotifyPropertyChanged
和 INotifyCollectionChanged
。
A multi-binding 仅在其中一个绑定中的属性之一发出 INotifyPropertyChanged.PropertyChanged
事件时才会更新。换句话说,如果 整个集合 底层 Textures
或 GameObjects
被完全替换为 ObservableCollection
的全新实例
但是,当您 add/remove 项 to/from 和 ObservableCollection
时,情况并非如此。那样的话,属性那个returns那个集合对象根本就不会变;完全相同的 ObservableCollection
对象仍然存在。但是集合 本身 引发了 INotifyCollectionChanged.CollectionChanged
事件。
WPF 对此做出反应的唯一方法是,如果某个对象正在监视 INotifyCollectionChanged
的特定 ObservableCollection
对象。当您在 MultiBinding
中使用它时,这不可能发生,因为 ObservableCollection
在转换中丢失了。 MultiBinding
returns 一个单独的值,无论该值是什么,它都不是实现 INotifyCollectionChanged
.
的任何对象
您可能想查看 CompositeCollection
class。这可能是更好的方法
我有一个 ItemsControl
是这样设置的:
<ItemsControl ItemsSource="{Binding GameObjects}"
AlternationCount="{Binding GameObjects.Count}"
Grid.RowSpan="10"
Grid.ColumnSpan="10">
<DataTemplate>
<Grid>
<Grid.DataContext>
<vm:MainWindowViewModel/>
</Grid.DataContext>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource TemplatedParent}}"/>
<Image>
<Image.Source>
<MultiBinding Converter="{StaticResource
ObservableCollectionItemByAlternationIndex}">
<Binding Path="Textures"/>
<Binding Path="GameObjects"/>
<Binding Path="(ItemsControl.AlternationIndex)"
RelativeSource="{RelativeSource TemplatedParent}"/>
</MultiBinding>
</Image.Source>
</Image>
</Grid>
</DataTemplate>
转换器如下所示:
public override object Convert(object[] v, Type t, object p, CultureInfo c)
{
var value1 = (ObservableCollection<string>)v[0];
var value2 = (ObservableCollection<GameObject>)v[1];
var value3 = (int)v[2];
foreach(var tex in value1)
{
if ("/Maelstrom;component//Data/Resources/Textures/" + value2[value3].GetType().Name + ".png" == tex)
{
return new BitmapImage(new Uri("pack://application:,,," + tex));
}
}
return new BitmapImage(new Uri("pack://application:,,," + value1[0]));
}
这里的问题是,当我更新 GameObjects
时,转换器不会获取 GameObjects
的更新版本,value1
将包含 value1
中的所有元素=14=] 程序启动时。 ItemsControl
更新正常(从 GameObjects
中删除的项目也从 UI 中删除)。
问题是您混淆了 INotifyPropertyChanged
和 INotifyCollectionChanged
。
A multi-binding 仅在其中一个绑定中的属性之一发出 INotifyPropertyChanged.PropertyChanged
事件时才会更新。换句话说,如果 整个集合 底层 Textures
或 GameObjects
被完全替换为 ObservableCollection
但是,当您 add/remove 项 to/from 和 ObservableCollection
时,情况并非如此。那样的话,属性那个returns那个集合对象根本就不会变;完全相同的 ObservableCollection
对象仍然存在。但是集合 本身 引发了 INotifyCollectionChanged.CollectionChanged
事件。
WPF 对此做出反应的唯一方法是,如果某个对象正在监视 INotifyCollectionChanged
的特定 ObservableCollection
对象。当您在 MultiBinding
中使用它时,这不可能发生,因为 ObservableCollection
在转换中丢失了。 MultiBinding
returns 一个单独的值,无论该值是什么,它都不是实现 INotifyCollectionChanged
.
您可能想查看 CompositeCollection
class。这可能是更好的方法