2012-02-21 15 views
5

Estoy intentando enlazar a un Dictionary<Type,string> a través de xaml.Enlace de marcado XAML al diccionario con la clave del tipo Tipo

El problema es que el indexador [] en la extensión de marcado Binding interpreta su contenido como una cadena. ¿Hay algún tipo de 'secuencia de escape' para ese caso?

<TextBox Text="{Binding theDictionary[{x:Type ns:OnePrettyType}]}" /> 

(unión no funciona porque {x:Type ns:OnePrettyType} se está enviando como cadena)

+0

En lugar de enlazar al diccionario y algún otro valor, exponer una propiedad en el modelo de vista que hace el trabajo por usted. –

Respuesta

10

Si el indexador tiene un tipo específico de la conversión debe hacerse de forma automática por lo que este debería funcionar:

{Binding theDictionary[ns:OnePrettyType]} 

Si necesita una interpretación explícita, puede intentar un "molde" como este:

{Binding theDictionary[(sys:Type)ns:OnePrettyType]} 

(Donde sys está mapeado en el espacio de nombres System por supuesto)

Esa sería la teoría pero todo eso no funcionará. En primer lugar, si utiliza el constructor Binding que toma una ruta, el molde se ignorará, ya que utiliza un determinado constructor de PropertyPath de una determinada manera. También obtendrá un error de unión:

System.Windows.Data Error: 40 : BindingExpression path error: '[]' property not found on 'object' ''Dictionary`2'

Usted tendría que hacer construir el PropertyPath a través del convertidor de tipos, al evitar la Binding constructor:

{Binding Path=theDictionary[(sys:Type)ns:OnePrettyType]} 

Ahora bien, esto lo más probable es simplemente una excepción :

{"Path indexer parameter has value that cannot be resolved to specified type: 'sys:Type'"}

Desafortunadamente, no hay ninguna conversión de tipo predeterminado en curso. Luego puede construir un PropertyPath en XAML y asegurarse de que se ingrese un tipo, pero la clase no está destinada a usarse en XAML y arrojará una excepción si lo intenta, también muy desafortunado.

Una solución alternativa sería crear una extensión de marcado que realice la construcción, p.

[ContentProperty("Parameters")] 
public class PathConstructor : MarkupExtension 
{ 
    public string Path { get; set; } 
    public IList Parameters { get; set; } 

    public PathConstructor() 
    { 
     Parameters = new List<object>(); 
    } 
    public PathConstructor(string path, object p0) 
    { 
     Path = path; 
     Parameters = new[] { p0 }; 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return new PropertyPath(Path, Parameters.Cast<object>().ToArray()); 
    } 
} 

que luego puede ser utilizada como esto:

<Binding> 
    <Binding.Path> 
     <me:PathConstructor Path="theDictionary[(0)]"> 
      <x:Type TypeName="ns:OnePrettyType" /> 
     </me:PathConstructor> 
    </Binding.Path> 
</Binding> 

o como esta actualización

{Binding Path={me:PathConstructor theDictionary[(0)], {x:Type ns:OnePrettyType}}} 
+0

gracias, H.B. - me impresionas. Parece que solo han pasado unos meses desde que pasaste 10k y ahora te estás acercando a los 40k. Gracias por todas estas respuestas de calidad que brinda. esto se ve bien, probablemente lo marcaré una vez que lo intente. –

+0

vaca santa, mira lo que he hecho. Siempre pensé que 'encuadernación no es extensible'. [Este] (http://stackoverflow.com/a/9377298/193320) se siente cerca de él. –

+0

@ MarkusHütter: Paso demasiado tiempo en este sitio. No te conocía, podrías tener múltiples parámetros de constructor en una extensión de marcado, gracias por eso, esa es una forma interesante de insertarlo. Intenté usar 'params' antes, pero desafortunadamente el compliner no lo entiende, hubiera sido perfecto. Aunque no sé cómo pasar el enlace, creo que es un poco más difícil de leer, me limitaría a usarlo en el 'Camino' como' {Binding Path = {me: ParameterPath [(0)], ...}} ' –

2

: dejo esto como referencia para extender enlaces

<Grid Width="{my:ParameterBinding {Binding [(0)],Source={x:Static my:SettingsService.Current}, Mode=TwoWay},{x:Type my:LeftPanelWidthSetting}}"/> 

, y ese es el código detrás

[ContentProperty("Parameters")] 
public class ParameterBinding : MarkupExtension 
{ 
    public Binding Binding { get; set; } 
    public IList Parameters { get; set; } 

    public ParameterBinding() 
    { 
     Parameters = new List<object>(); 
    } 

    public ParameterBinding(Binding b, object p0) 
    { 
     Binding = b; 
     Parameters = new []{p0}; 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     Binding.Path = new PropertyPath(Binding.Path.Path, Parameters.Cast<object>().ToArray()); 
     return Binding.ProvideValue(serviceProvider); 
    } 
} 

esto sería extensible para soportar más parámetros en la sintaxis en línea con los constructores adicionales. Aún me queda la posibilidad de agregar muchos parámetros con la sintaxis del elemento extendido.

thx to H.B.para inspirar esto

Cuestiones relacionadas