简体   繁体   English

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

[英]Create a collection in XAML and bind individual collection items

I've created a custom control which, when bound to a custom collection of objects, displays the content of those objects. 我创建了一个自定义控件,当绑定到对象的自定义集合时,该控件将显示这些对象的内容。

Usually, I can use this control by simply going: 通常,我可以通过以下方式使用此控件:

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

My problem now comes where I want to recycle this control to show only a single object. 我的问题现在出现在我想回收该控件以仅显示单个对象的地方。 In the xaml, I want to make a custom collection where the only item in the collection is bound to that single object. 在xaml中,我想创建一个自定义集合,其中集合中的唯一项绑定到该单个对象。

The code looks like this: 代码如下:

<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>

Obviously, there's no 'Reference' property which I can use to make the CustomItem in the collection point to the instance of CustomItem in 'SomeClass'. 显然,没有“ Reference”属性,可以用来使集合中的CustomItem指向“ SomeClass”中CustomItem的实例。 How can I achieve this without creating a dummy CustomCollection containing this CustomItem in my object viewmodel? 如何在不创建包含对象Viewmodel中包含此CustomItem的虚拟CustomCollection的情况下实现此目标?

There already is a x:Reference markup extension , but it is very limited as it only gets objects by name. 已经有一个x:Reference标记扩展 ,但是它非常有限,因为它仅按名称获取对象。 You could write your own markup-extension which can get properties. 您可以编写自己的标记扩展来获取属性。 eg 例如

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);
        }
    }
}

Which could be used like this: 可以这样使用:

<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>

You could also resolve a whole PropertyPath at once in the extension if you prefer that, this is just a sketchy example. 如果愿意,您也可以一次在扩展中解析整个PropertyPath ,这只是一个粗略的示例。


Another option is to bind the DataContext directly to the object and wrap it in the collection using a Converter . 另一个选择是将DataContext直接绑定到对象,并使用Converter将其包装在集合中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM