我正在使用C#和.NET 4.5来创建MVVM桌面应用程序。我有一组已包含在ObservableCollection<MyEntryClass>
中的视图模型条目。
我需要使用第三方控件来显示数据。此控件要求将条目转换为自己的条目类。他们使用XAML和IValueConverter
提供了如何执行此操作的示例。归结为...Items="{Binding Path=The.Source, Converter={StaticResource CustomDataConverter}}...
和一个大致如下所示的转换器:
public class CustomDataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
IEnumerable<CustomItem> dataContext = value as IEnumerable<CustomItem>;
ObservableCollection<OutputItem> items = new ObservableCollection<OutputItem>();
foreach (CustomItem customItem in dataContext)
{
OutputItemitem =
new OutputItem
{
// ... some value transfers ...
};
items.Add(item);
}
return items;
}
虽然这适用于控件的初始化,但它会破坏&#34;观察链&#34;控件和绑定中指定的ObservableCollection
之间 - 只是因为自定义转换器创建自己的项列表。有没有办法更改绑定指令,以便不为整个源集合调用转换器一次,而是为每个集合元素调用一次?如果没有,有什么替代策略来处理这种情况?
(在上面的示例中,我省略了一些代码,它们将事件处理程序注册到源对象的PropertyChanged
事件并更新目标对象。各个项属性的更新工作正常,它&# 39; s只是未处理的列表更新。)
编辑:有问题的第三方控件是来自GanttChartDataGrid的Gantt Chart Light Library。
答案 0 :(得分:3)
如果此第三方控件提供此类可能性,您可以尝试在ItemTemplate中使用转换器。使用标准的WPF控件,它应该是这样的:
<ListBox ItemsSource="{Binding Path=The.Source}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Converter={StaticResource CustomDataConverter}}"
ContentTemplate="{StaticResource MyOptionalDataTemplate}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
但实现这一目标的最简单方法可能是绑定包含OutputItems的集合......
答案 1 :(得分:0)
另一种方法可能是忘记在XAML代码中使用转换器并在ViewModel中进行转换。
您发布的转换器没有ConvertBack
方法,因此我猜测您的第三部分控件所需的ObservableCollection<OutputItem>
列表是只读的,这意味着从XAML到C#不会发生任何修改 - 正如大家所想的那样使用Grafic Chart库。
因此,您可以拥有2个属性,一个私有包含您将根据您的业务逻辑在ViewModel中更新的自定义对象,然后将一个公共属性绑定到您的第三个部分UserControl:
private ObservableCollection<OutputItem> myPrivateData
{
get;
set;
}
private ObservableCollection<CustomItem> DataToPlotOnGant
{
get;
set;
}
然后,您可以在私人收藏的CollectionChanged
事件中进行转换:
this.myPrivateData.CollectionChanged += (s, e) =>
{
// do convertion stuff here
};
并选择更新DataToPlotOnGant
列表,只修改私有集合中更改的项目 - 更有效 - 或者每次像转换器那样创建新集合时都会创建。{/ p>