2017-04-26 66 views
1

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

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

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

最后,我担心我可能不得不放弃,切换到Dictionary<string, double>,并让字符串成为元组中类型的连接,例如,通过让每个键是string key = SomeEnum.SomeValue + "," + someDouble + "," + someString,但我真的只是喜欢做到这一点。如果有帮助,我愿意将Tuple更改为另一种非字符串类型。也许一些其他不可变的类型?我不是非常精通C#数据绑定超越基础知识,所以任何帮助或想法都非常感激。

+0

这可能会回答你的问题:HTTP:// stackoverflow.com/a/43209056/880990 –

+0

感谢Olivier,但这是对于新的C#7价值元组类型。我使用的是旧的C#6 Tuple类型,它是可绑定的。见例如https://msdn.microsoft.com/en-us/library/dd386940(v=vs.110).aspx。所以我不确定你发布的问题能否帮助我。 – TheIntern

回答

1

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

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

- PropertyPath XAML Syntax

但是,在创建Tuple内的XAML路径可以是相当困难的。有2个解决这个:

  1. 创建自定义标记扩展生成Tuple
  2. 创建支持多索引

最简单和干净的词典可能是解决方案#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; } 
    } 
} 
+0

非常优雅的替代解决方案。谢谢! – TheIntern