绑定到多个源

时间:2013-06-11 17:48:55

标签: c# wpf binding collections

我正在使用D3绘制图表。在这一刻,我通过这种方式绑定:

<d3:ChartPlotter x:Name="plotter" ItemsSource="Charts" Margin="20">

我在图表中添加/删除项目,并自动更新绘图仪。效果很好。

问题是我需要绑定几个集合,但显然我不能设置ItemsSource两次。我已经阅读了有关CompositeCollections的内容,但几乎所有文章都基于StaticResource,这不是我的理由。

 <d3:ChartPlotter x:Name="plotter"Margin="20">
 <d3:ChartPlotter.ItemsSource>
    <CompositeCollection>
      <CollectionContainer Collection="{Binding Charts}" />
      <CollectionContainer Collection="{Binding Charts2}" />
      </CompositeCollection>
  </d3:ChartPlotter.ItemsSource>

此代码编译但绑定不起作用。

我经常搜索,但令人惊讶的是我找不到答案。我认为这必须是WPF中的常见任务。

我对将多个集合绑定到单个ItemsSource的其他方法持开放态度,但是手动将每个子集合中的每个项目添加到Charts我觉得它太麻烦了。谢谢。

编辑:

我正在尝试通过MultiBinding进行,这是转换器的方案

EDIT2:

图表是ObservableCollection<LineGraph>

public class ConcatConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<LineGraph> enumerables = new ObservableCollection<LineGraph>();

        foreach (LineGraph line in values[0])
        {
            enumerables.Add(line);
        }

        foreach (LineGraph line in values[1])
        {
            enumerables.Add(line);
        }

        return enumerables;

    }
    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

由于这个错误我无法编译:“foreach语句加农炮在”对象“类型的变量中运行,因为”对象“不包含”GetEnumerator“的公共定义。

1 个答案:

答案 0 :(得分:1)

使用MultiBinding。首先,制作一个可以做你想做的转换器:

public class ConcatConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        List<IEnumerable> enumerables = new List<IEnumerable>();
        foreach (object obj in values)
        {
            IEnumerable temp = obj as IEnumerable;
            if (temp == null) throw new ArgumentException();
            enumerables.Add(temp);
        }
        List<dynamic> enDynamic = new List<dynamic>();
        enDynamic.AddRange(enumerables);
        return Concat((dynamic)enDynamic);
    }
    private IEnumerable<T> Concat<T>(params IEnumerable<T>[] toConcat)
    {
        return toConcat.Aggregate((a, b) => a.Concat(b));
    }
    private IEnumerable Concat(params IEnumerable[] toConcat)
    {
        ArrayList temp = new ArrayList();
        foreach (IEnumerable x in toConcat)
        {
            foreach (object n in x)
            {
                temp.Add(n);
            }
        }
        return temp;
    }
    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

(非通用但我不想使用钝的反射量)

然后将其添加到您窗口的资源中:

<!--in your window declaration-->
xmlns:local="clr-namespace:YourNameSpace"
<!--after that-->
<Window.Resources>
    <ttp:ConcatConverter x:Key="Concat"/>
</Window.Resources>
<!--finally:-->
<d3:ChartPlotter.ItemsSource>
    <MultiBinding Converter="{StaticResource ResourceKey=Concat}">    
        <Binding Source="Charts"/>
        <Binding Source="Charts2"/>
    </MultiBinding>
</d3:ChartPlotter.ItemsSource>