Pregunta

Quiero mostrar datos en una cuadrícula de datos wpftoolkit donde los datos son una colección de

public class Thing
{
    public string Foo { get; set; }
    public string Bar { get; set; }
    public List<Candidate> Candidates { get; set; }
}

public class Candidate
{

    public string Name { get; set; }
    public CandidateType CandidateType { get; set; }
}

public enum CandidateType
{
    Type1,
    Type2,
    Type42
}

donde el número de candidatos en la lista de candidatos es configurable en tiempo de ejecución.

El diseño de cuadrícula deseado se ve así

Foo | Bar | Candidato 1 | Candidato 2 | ... | Candidato N

Por lo tanto, parece que no puedo crear un DataTemplate para los candidatos en xaml ya que la expresión de enlace cambiará.

Agrego columnas necesarias en el evento AutoGeneratedColumns de esta manera:

private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
{
    ViewModel vm = DataContext as ViewModel;

    for (int i = 0; i < vm.LotsOfThings.First().Candidates.Count; i++)
    {
        string assName = Assembly.GetExecutingAssembly().GetName().Name;
        ParserContext ctx = new ParserContext();
        ctx.XamlTypeMapper = new XamlTypeMapper(new string[] { assName });
        ctx.XamlTypeMapper.AddMappingProcessingInstruction("src", "WpfToolkitDataGridTester", assName);
        ctx.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
        ctx.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
        ctx.XmlnsDictionary.Add("src", "clr-namespace:WpfToolkitDataGridTester;assembly=" + assName);
        var template = XamlReader.Parse(@"<DataTemplate>
                                            <DataTemplate.Resources>
                                                <src:FooConverter x:Key='fooConverter' />
                                            </DataTemplate.Resources>
                                            <TextBlock  
                                                Foreground='{Binding Candidates[" + i + @"].CandidateType,Converter={StaticResource fooConverter}}'
                                                Text='{Binding Candidates[" + i + @"].Name}' />
                                        </DataTemplate>", ctx) as DataTemplate;
        dg.Columns.Add(new DataGridTemplateColumn
        {
            Header = "Candidate " + (i + 1),
            CellTemplate = template
        });
    }
}

Sin embargo, esto falla con la siguiente excepción: La etiqueta 'FooConverter' no existe en el espacio de nombres XML 'clr-namespace: WpfToolkitDataGridTester; assembly = WpfToolkitDataGridTester'. Línea '3' Posición '54'.

Cambiar el StaticResource a DynamicResource no hace ningún cambio.

¿Qué me estoy perdiendo?

FWIW: una plantilla de datos codificada

<DataTemplate x:Key="candidateTemplate">
  <DataTemplate.Resources>
    <src:FooConverter x:Key="fooConverter" />
  </DataTemplate.Resources>
  <TextBlock 
    Foreground="{Binding Candidates[0].CandidateType,Converter={StaticResource fooConverter}}"
    Text="{Binding Candidates[0].Name}" />
</DataTemplate>

y la columna de plantilla definida así

<wpftk:DataGridTemplateColumn CellTemplate="{StaticResource candidateTemplate}" />

'funciona' pero obviamente no produce el resultado deseado ya que Candidates [0] está codificado.

¿Fue útil?

Solución

Por alguna razón, funciona como se espera si me gusta esto ...

    string assName = Assembly.GetExecutingAssembly().GetName().Name;
    StringBuilder sb = new StringBuilder();
    sb.Append("<DataTemplate ");
    sb.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
    sb.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
    sb.Append("xmlns:src='clr-namespace:WpfToolkitDataGridTester;assembly=" + assName + "' >");
    sb.Append("<DataTemplate.Resources>");
    sb.Append("<src:FooConverter x:Key='fooConverter' />");
    sb.Append("</DataTemplate.Resources>");
    sb.Append("<TextBlock ");
    sb.Append("Foreground='{Binding Candidates[" + i + "].CandidateType,Converter={StaticResource fooConverter}}' ");
    sb.Append("Text='{Binding Candidates[" + i + @"].Name}' />");
    sb.Append("</DataTemplate>");
    var template = (DataTemplate)XamlReader.Parse(sb.ToString());

Otros consejos

Cuando los archivos XAML se compilan en BAML, hace referencia al ensamblaje no al origen en memoria. Dado que BAML se compila en el mismo ensamblaje, el tipo real aún no está disponible.

He descubierto que una solución temporal a corto plazo es comentar el estilo temporalmente, construir el proyecto y luego restaurar el estilo.

Sin embargo, la solución más permanente es mover el convertidor a otro ensamblaje.

¿Sería útil declarar el FooConverter una vez a un nivel superior (tal vez como un recurso de DataGrid ) en lugar de en cada DataTemplate ?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top