将元素列表绑定到WPF中基于集合的依赖项属性

时间:2014-11-11 21:50:45

标签: c# wpf xaml

我在WPF应用程序(.Net 4.5)中实现自定义Blend行为。我已经在行为类中添加了几个FrameworkElement类型的依赖项属性,以允许行为的用户绑定他们想要控制的视图的元素。 (此行为会在多个元素上调用一些动画,因此我无法使用AssociatedObject)。这很好,基本上看起来像这样:

public class MyBehavior : Behavior<FrameworkElement>
{
    public static readonly DependencyProperty Element1Property = DependencyProperty.Register("Element1", typeof (FrameworkElement), typeof (MyBehavior), new UIPropertyMetadata());

    public FrameworkElement Element1
    {
        get { return (FrameworkElement) GetValue(Element1Property); }
        set { SetValue(Element1Property, value); }
    }

    public static readonly DependencyProperty Element2Property = DependencyProperty.Register("Element2", typeof(FrameworkElement), typeof(MyBehavior), new UIPropertyMetadata());

    public FrameworkElement Element2
    {
        get { return (FrameworkElement) GetValue(Element2Property); }
        set { SetValue(Element2Property, value); }
    }
}

标准依赖属性。我可以在我看来像这样使用它:

<Grid x:Name="Container">
    <i:Interaction:Behaviors>
        <local:MyBehavior
            Element1="{Binding ElementName=FirstElement}"
            Element2="{Binding ElementName=SecondElement}"
        />
    </i:Interaction:Behaviors>
</Grid>

这很有用,我可以使用行为中的元素。但是现在我需要绑定像这样的元素列表。因此,我事先并不知道将会有2个元素,可能需要使用N个元素。所以我已经在MyBehavior类中添加了另一个属性,如下所示:

public static readonly DependencyProperty ElementsProperty = DependencyProperty.Register("Elements", typeof(List<FrameworkElement>), typeof(MyBehavior), new UIPropertyMetadata(new List<FrameworkElement>()));

public List<FrameworkElement> Elements
{
    get { return (List<FrameworkElement>) GetValue(ElementsProperty); }
    set { SetValue(ElementsProperty, value); }
}

(我已按照建议here初始化行为构造函数中的列表。)但我无法弄清楚如何将元素列表绑定到此来自XAML视图的财产。基本上,我想沿着这些方向做点什么:

<Grid x:Name="Container">
    <i:Interaction:Behaviors>
        <local:MyBehavior>
            <local:MyBehavior.Elements>
                <Binding ElementName="FirstElement" />
                <Binding ElementName="SecondElement" />
                <Binding ElementName="ThirdElement" />
            </local:MyBehavior.Elements>
        </local:MyBehavior>
    </i:Interaction:Behaviors>
</Grid>

但当然这实际上并不奏效。我在这里尝试过MultiBinding,但这也不起作用。知道XAML语法是做什么的,或者甚至是可能的?如果不可能,有任何其他方法可以实现这种效果吗?谢谢!

1 个答案:

答案 0 :(得分:1)

我最终解决了这个问题。事实证明,我可以使用MultiBinding。转换器看起来像这样:

public class MultiFrameworkElementConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values != null ?
            values.Cast<FrameworkElement>().ToList() :
            new List<FrameworkElement>();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我应该在该转换器中更加彻底,并确保values []数组中的所有对象都是FrameworkElement类型,但这可以解决这个问题。然后在XAML中我可以像我这样绑定属性:

<local:MyBehavior.Elements>
    <MultiBinding Converter="{StaticResource MultiFrameworkElementConverter}" Mode="OneTime">
        <Binding ElementName="FirstElement" />
        <Binding ElementName="SecondElement" />
        <Binding ElementName="ThirdElement" />
    </MultiBinding>
</local:MyBehavior.Elements>

我正在使用&#34; OneTime&#34;绑定模式只是因为这些是视图中的UI元素,我绑定到了行为。它们在视图和行为的生命周期中永远不会改变。因此无需更新绑定。

总的来说,我对此表示满意。我现在可以允许行为影响任意UI元素列表,无论我使用哪个视图。我希望这个描述能够帮助其他人尝试做类似的事情。