在XAML中创建一个集合并绑定各个集合项

时间:2011-09-27 15:05:45

标签: wpf xaml .net-3.5

我创建了一个自定义控件,当绑定到自定义对象集合时,会显示这些对象的内容。

通常,我可以通过简单地使用此控件:

<local:CustomCollectionDisplayer DataContext="{Binding Source={x:Static Application.Current}, Path=SomeObject.InstanceOfCustomeCollectionOfCustomItems}" />

现在我的问题出现在我要回收此控件以仅显示单个对象的位置。在xaml中,我想创建一个自定义集合,其中集合中唯一的项目绑定到该单个对象。

代码如下所示:

<local:CustomCollectionDisplayer>
    <local:CustomCollectionDisplayer.DataContext>
        <local:CustomCollection>
            <local:CustomItem Reference="{Binding Source={x:Static Application.Current}, Path=SomeObject.InstanceOfCustomItem}"/>-->
        </local:CustomCollection>
    </local:CustomCollectionDisplayer.DataContext>
</local:CustomCollectionDisplayer>

显然,没有'Reference'属性可以用来使集合中的CustomItem指向'SomeClass'中的CustomItem实例。如何在不在对象视图模型中创建包含此CustomItem的虚拟CustomCollection的情况下实现此目的?

1 个答案:

答案 0 :(得分:1)

已经存在x:Reference markup extension,但它非常有限,因为它只按名称获取对象。您可以编写自己的markup-extension来获取属性。 e.g。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.ComponentModel;

namespace Test.MarkupExtensions
{
    [ContentProperty("Object")]
    public class GetExtension : MarkupExtension
    {
        public object Object { get; set; }
        public string PropertyName { get; set; }

        public GetExtension() { }
        public GetExtension(string propertyName)
            : this()
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
            PropertyName = propertyName;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (PropertyName == null)
                throw new InvalidOperationException("PropertyName cannot be null");
            if (Object == null)
            {
                var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
                Object = target.TargetObject;
            }
            var prop = Object.GetType().GetProperty(PropertyName);
            if (prop == null)
                throw new Exception(String.Format("Property '{0}' not found on object of type {1}.", PropertyName, Object.GetType()));
            return prop.GetValue(Object, null);
        }
    }
}

可以这样使用:

<local:CustomCollectionDisplayer>
    <local:CustomCollectionDisplayer.DataContext>
        <local:CustomCollection>
            <me:Get PropertyName="InstanceOfCustomItem">
                <me:Get PropertyName="SomeObject" Object="{x:Static Application.Current}"/>
            </me:Get>
        </local:CustomCollection>
    </local:CustomCollectionDisplayer.DataContext>
</local:CustomCollectionDisplayer>

如果您愿意,也可以在扩展程序中同时解析整个PropertyPath,这只是一个粗略的示例。


另一种选择是将DataContext直接绑定到对象,并使用Converter将其包装在集合中。