2009-03-16 5 views
1

Je veux afficher les données dans un DataGrid wpftoolkit où les données est une collection deDataTemplate dynamique avec valueconverter

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 
} 

où le nombre de candidats dans la liste des candidats est configurable lors de l'exécution.

présentation de la grille souhaitée ressemble à ceci

Foo | Bar | Candidate 1 | Candidate 2 | ... | Candidate N

Ainsi, il semble que je ne peux pas créer un DataTemplate pour les candidats en XAML comme l'expression de liaison changera.

j'ajouter des colonnes nécessaires événement AutoGeneratedColumns comme ceci:

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 
     }); 
    } 
} 

Cela échoue cependant à l'exception suivante: La balise 'FooConverter' n'existe pas dans clr-namespace » espace de noms XML: WpfToolkitDataGridTester; assemblage = WpfToolkitDataGridTester '. Ligne '3' Position '54'.

La modification de StaticResource à DynamicResource n'apporte aucune modification.

Qu'est-ce qui me manque?

FWIW: DataTemplate hardcoded

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

et la colonne de modèle défini comme si

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

'fonctionne', mais évidemment ne produit pas le résultat souhaité que les candidats [0] est hardcoded.

Répondre

2

Pour une raison quelconque, il fonctionne comme prévu si je fais comme ça ...

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()); 
0

Serait-il utile de déclarer le FooConverter une fois à un niveau supérieur (peut-être comme une ressource du DataGrid) au lieu de dans chaque DataTemplate?

+0

J'ai essayé cela aussi, cela n'a pas fonctionné non plus. Je suppose qu'une partie de la raison est que XamlParser ne le trouvera pas s'il n'est pas dans la chaîne pour analyser. – mostlytech

1

Lorsque les fichiers XAML sont compilés à BAML il fait référence à l'ensemble pas dans la source de la mémoire. Puisque le BAML est compilé dans le même assemblage, le type réel n'est pas encore disponible.

J'ai découvert qu'une solution de contournement à court terme consiste à commenter temporairement le style, à générer le projet, puis à restaurer le style.

La solution la plus permanente consiste cependant à déplacer le convertisseur vers un autre ensemble.

Questions connexes