使用C#中的Tuple键绑定到字典的数据

时间:2017-04-26 20:58:14

标签: c# .net dictionary data-binding tuples

我有一个Dictionary<Tuple<SomeEnum, double, string>, double>,我试图在Xamarin中绑定。我只是试图将值(双精度)绑定到标签上,没什么特别花哨的。我遇到的问题是我无法找出绑定到元组键的路径语法。我知道用Dictionary<string, double>我会让Path="[" + keyString + "]",例如,但是如果我想使用元组作为键,我就无法弄清楚该做什么。即使Microsoft's page on data binding path syntax in C#似乎没有明确处理这种情况,但它确实注意到了

  

在内部索引器中,您可以使用逗号(,)分隔多个索引器参数。可以使用括号指定每个参数的类型。例如,您可以拥有Path="[(sys:Int32)42,(sys:Int32)24]",其中sys映射到System名称空间。

现在,我假设这也适用于单个索引器对象。所以在我的字典中,我想我会有类似Path="[(sys:Tuple<SomeEnum, sys:double, sys:string>)???]"的东西,但我不确定???的位置。而且我不确定在SomeEnum之前我是否需要名称空间。最后,我似乎无法找到更详细的文档。所以我会在这些方面采取任何帮助。

最终,我担心我可能不得不放弃,切换到Dictionary<string, double>,并让字符串成为元组中类型的.ToString()串联,例如让每个键都为string key = SomeEnum.SomeValue + "," + someDouble + "," + someString,但我真的更喜欢这样做。如果有帮助的话,我可以将Tuple更改为另一种非字符串类型。也许其他一些不可变的类型?我对C#数据绑定并不十分精通基础知识,因此非常感谢任何帮助或想法。

1 个答案:

答案 0 :(得分:1)

实际上,数据绑定支持多索引器。语法如下:

<object Path="[index1,index2...]" .../>  
or  
<object Path="propertyName[index,index2...]" .../>
     

- PropertyPath XAML Syntax

但是,在XAML路径中创建Tuple可能非常困难。有两个解决方案:

  1. 创建自定义标记扩展程序以生成Tuple
  2. 创建支持多索引器的词典
  3. 最简单,最干净的可能是解决方案#2。 (PathToDictionary[{ns:Tuple a,b,c}] vs PathToDictionary[a,b,c])。

    将此用作词典:

    public class TripleKeyedDictionary<TKey1, TKey2, TKey3, TValue> : Dictionary<Tuple<TKey1, TKey2, TKey3>, TValue>
    {
        public TValue this [TKey1 key1, TKey2 key2, TKey3 key3]
        {
            get { return this[Tuple.Create(key1, key2, key3)]; }
            set { this[Tuple.Create(key1, key2, key3)] = value; }
        }
    }
    

    使用示例:PathToDictionary[Banana,b,c]

    LINQPad的完整示例:

    void Main()
    {
        var data = new
        {
            Lookup = new TripleKeyedDictionary<Fruit, string, string, string>
            {
                { Tuple.Create(Fruit.Banana, "b", "c"), "value" }
            }
        };
    
        var binding = new Binding("Lookup[Banana,b,c]");
        binding.Mode = BindingMode.OneWay;
        binding.Source = data;
        binding.FallbackValue = "fallback";
        binding.TargetNullValue = "null";
    
        var block = new TextBlock().Dump();
        block.SetBinding(TextBlock.TextProperty, binding);
    }
    
    // Define other methods and classes here
    public enum Fruit
    {
        Apple, Banana, Cactus
    }
    public class TripleKeyedDictionary<TKey1, TKey2, TKey3, TValue> : Dictionary<Tuple<TKey1, TKey2, TKey3>, TValue>
    {
        public TValue this [TKey1 key1, TKey2 key2, TKey3 key3]
        {
            get { return this[Tuple.Create(key1, key2, key3)]; }
            set { this[Tuple.Create(key1, key2, key3)] = value; }
        }
    }