【问题标题】:Adding SortedList or Dictionary<int, string> to ResourceDictionary将 SortedList 或 Dictionary<int, string> 添加到 ResourceDictionary
【发布时间】:2012-03-15 23:30:26
【问题描述】:

有没有办法将 SortedList 或 Dictionary 添加到 ResourceDictionary 并通过 XAML 使用(并绑定!)它到控件?

我试过这个,但我不知道怎么做:

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

【问题讨论】:

  • x:Array 如果您按顺序添加 values 就可以了,您只需添加第一个 &lt;sys:String&gt; 并获得索引 0 等等,然后绑定可以使用 [0] 定位索引器。

标签: c# wpf xaml


【解决方案1】:

SortedList 很简单,因为它不是通用的。

如果一个类实现了IDictionary,您可以通过将它们定义为子节点来添加值,使用x:Key 来设置它们应该被添加到字典中的键。

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}}" />

这里的项目键是字符串,要获取实际的整数,您可以使用将字符串解析为整数的自定义标记扩展,或者首先将键定义为资源:

<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,否则它会被解释为字符串。

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

不能因为implementation detail而省略Path=


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

在这样的扩展上实现IDictionary 还允许您填充新创建的实例。这是一个非常粗略的示例

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 中进行转换(这可能会导致某些类型出现问题)。

由于字典本身是键入的,因此绑定应该需要强制转换。

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

【讨论】:

  • 它不适用于 silverlight 4 ,我尝试添加 MarkupExtension 但即使添加命名空间也不存在,任何解决方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2019-01-29
  • 2011-03-05
  • 2010-10-17
相关资源
最近更新 更多