添加SortedList或Dictionary< int,string>到ResourceDictionary [英] Adding SortedList or Dictionary<int, string> to ResourceDictionary

查看:86
本文介绍了添加SortedList或Dictionary< int,string>到ResourceDictionary的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以将SortedList或Dictionary添加到ResourceDictionary并通过XAML将其使用(并绑定!)到控件上?

Is there a way to add a SortedList or a Dictionary to a ResourceDictionary and use (and bind!) it to a control via XAML?

这,但我不知道该怎么做:

I've tried this, but I couldn't figure out how to do it:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:coll="clr-namespace:System.Collections.Generic;assembly=mscorlib">

    <x:Array x:Key="test"
             Type="sys:Object">
        <coll:KeyValuePair>***</coll:KeyValuePair>
    </x:Array>


推荐答案

SortedList 很容易,因为它不是通用的。

SortedList is easy as it is not generic.

如果类实现了 IDictionary 可以通过使用<$ c $将它们定义为子节点来添加值c> x:Key 设置将其添加到字典的密钥。

If a class implements IDictionary you can add values by defining them as the child nodes using x:Key to set the key by which they should be added to the dictionary.

xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"





<col:SortedList x:Key="list">
    <sys:String x:Key="0">Lorem</sys:String>
    <sys:String x:Key="1">Ipsum</sys:String>
    <sys:String x:Key="2">Dolor</sys:String>
    <sys:String x:Key="3">Sit</sys:String>
</col:SortedList>





<!-- Usage: -->
<ContentControl Content="{Binding [0], Source={StaticResource list}}" />

此处的项目关键字是字符串,要获取实际的整数,可以使用自定义标记扩展来解析要转换为int的字符串,或者首先将键定义为资源:

The item keys are strings here, to get actual ints you could use a custom markup extension which parses the string to int, or by defining the keys as resource first:

<sys:Int32 x:Key="key1">0</sys:Int32>
<sys:Int32 x:Key="key2">1</sys:Int32>
<sys:Int32 x:Key="key3">2</sys:Int32>
<sys:Int32 x:Key="key4">3</sys:Int32>

<col:SortedList x:Key="list">
    <sys:String x:Key="{StaticResource key1}">Lorem</sys:String>
    <sys:String x:Key="{StaticResource key2}">Ipsum</sys:String>
    <sys:String x:Key="{StaticResource key3}">Dolor</sys:String>
    <sys:String x:Key="{StaticResource key4}">Sit</sys:String>
</col:SortedList>

然后,绑定变得更加复杂,因为需要将索引器值显式转换为int,否则

The binding then becomes more complex as the indexer value needs to be cast to int explicitly as it otherwise would be interpreted as string.

<ContentControl Content="{Binding Path=[(sys:Int32)0],
                                  Source={StaticResource list}}"/>

不能省略 Path = 是因为实现细节

字典不是那么容易,因为它们是通用的,并且(目前)还没有一种简单的内置方法可以在XAML中创建通用对象。但是,可以使用标记扩展来通过反射来创建通用对象。

Dictionaries are not so easy because they are generic and there (currently) is no simple built-in way to create generic objects in XAML. Using markup extensions however you can create generic objects via reflection.

在这样的扩展上实现 IDictionary 也可以使您填充该新创建的实例。这是一个非常粗略的示例

Implementing IDictionary on such an extension also allows you to fill that newly created instance. Here is a very sketchy example:

public class DictionaryFactoryExtension : MarkupExtension, IDictionary
{
    public Type KeyType { get; set; }
    public Type ValueType { get; set; }

    private IDictionary _dictionary;
    private IDictionary Dictionary
    {
        get
        {
            if (_dictionary == null)
            {
                var type = typeof(Dictionary<,>);
                var dictType = type.MakeGenericType(KeyType, ValueType);
                _dictionary = (IDictionary)Activator.CreateInstance(dictType);
            }
            return _dictionary;
        }
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return Dictionary;
    }

    public void Add(object key, object value)
    {
        if (!KeyType.IsAssignableFrom(key.GetType()))
            key = TypeDescriptor.GetConverter(KeyType).ConvertFrom(key);
        Dictionary.Add(key, value);
    }

    #region Other Interface Members
    public void Clear()
    {
        throw new NotSupportedException();
    }
    public bool Contains(object key)
    {
        throw new NotSupportedException();
    }
    // <Many more members that do not matter one bit...>
    #endregion
}





<me:DictionaryFactory x:Key="dict" KeyType="sys:Int32" ValueType="sys:String">
    <sys:String x:Key="0">Lorem</sys:String>
    <sys:String x:Key="1">Ipsum</sys:String>
    <sys:String x:Key="2">Dolor</sys:String>
    <sys:String x:Key="3">Sit</sys:String>
</me:DictionaryFactory>

由于将类型化实例作为键传递,所以我选择在其中进行转换有点痛苦 IDictionary.Add ,然后将值添加到内部字典中(这可能会导致某些类型的问题)。

As passing in a typed instance as key is a bit of a pain i chose to do the conversion in IDictionary.Add before the value is added to the internal dictionary instead (this may cause problems with certain types).

由于键入了字典本身,因此绑定不需要强制转换。

Since the dictionary itself is typed the binding should not require a cast.

<ContentControl Content="{Binding [0], Source={StaticResource dict}}" />

这篇关于添加SortedList或Dictionary&lt; int,string&gt;到ResourceDictionary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆