2009-11-12 3 views
2

J'essaie de comprendre comment créer une liaison récursive dans xaml. Je connais HierarchialDataTemplate, mais ce n'est pas ce que je veux, car ma source de données n'est pas une collection d'éléments. Plus précisément, je construis un navigateur d'exceptions, et j'essaie de trouver la meilleure façon d'exprimer le champ InnerException de l'exception (qui est bien sûr une autre exception, donc récursive.)Wpf Recursive Binding

Ce navigateur d'exception fait partie d'une visionneuse de journal Je construis. Voici le XAML pour le ListView jusqu'ici:

<ListView x:Name="LogViewerOutput"> 
    <ListView.ItemTemplate> 
     <DataTemplate DataType="Ushanka.Log.LogMessageEventArgs"> 
      <Expander Style="{StaticResource ExceptionTreeStyle}" Width="Auto"> 
       <Expander.Header> 
        <StackPanel Orientation="Horizontal"> 
         <Image Stretch="Fill" Width="16" Height="16" Margin="5" 
           Source="{Binding Path=Level, Converter={StaticResource LogLevelIconConverter}}" /> 
         <TextBlock Text="{Binding Message}" /> 
        </StackPanel> 
       </Expander.Header> 
       <Expander.Content> 
        <StackPanel Orientation="Vertical"> 
         <TextBlock Text="{Binding Exception.Message}" /> 
         <TextBlock Text="{Binding Exception.Source" /> 
         <!-- Here I would like to somehow be able to recursively browse through the tree of InnerException --> 
        </StackPanel> 
       </Expander.Content> 
      </Expander> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

Des idées? Est-ce seulement possible?

Répondre

3

Je créer un DataTemplate pour une exception et lier l'InnerException à un ContentPresenter à l'intérieur. ContentPresenter arrêtera la chaîne lorsque InnerException est null et vous pouvez formater les exceptions comme vous le souhaitez. Quelque chose comme ceci:

<DataTemplate DataType="{x:Type Exception}"> 
    <StackPanel Orientation="Vertical"> 
     <TextBlock Text="{Binding Message}" /> 
     <TextBlock Text="{Binding Source" /> 
     <ContentPresenter Content="{Binding InnerException}" /> 
    </StackPanel> 
</DataTemplate> 
+0

Hmm. C'est très proche, mais il semble simplement rendre InnerException comme une chaîne. J'espérais qu'il pourrait être présenté de manière récursive (comme le navigateur d'exceptions de Visual Studio) de la même manière que l'exception de niveau supérieur. –

+0

Vous devrez peut-être assigner des clés au DataTemplate et l'assigner explicitement, mais vous allez probablement vous retrouver avec quelque chose comme ça. –

+0

Cela devrait fonctionner tel quel, mais vous devez le placer dans une collection Resources au-dessus du contrôle où vous liez l'exception externe, comme Window.Resources. Pour lancer la liaison récursive, vous devez simplement définir Expander.Content = "{Exception de liaison}" dans votre exemple ci-dessus. Je suppose qu'à ce stade, vous voudrez probablement aussi déplacer les choses de sorte que vous ayez peut-être des Expanders dans votre modèle d'Exception, mais vous pouvez l'essayer quand vous le faites fonctionner. –

0
Code

pour soutenir obtenir le type d'exception pour l'en-tête:

class TypeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value.GetType().ToString(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

XAML:

<Window.Resources> 

    <local:TypeConverter x:Key="TypeConverter"/> 

    <DataTemplate DataType="{x:Type sys:Exception}"> 
     <Expander Header="{Binding Converter={StaticResource TypeConverter}}"> 
      <Expander.Content> 
       <StackPanel Orientation="Vertical"> 
        <TextBlock Text="{Binding Message}" /> 
        <TextBlock Text="{Binding Source}" /> 
        <ContentPresenter Content="{Binding InnerException}" /> 
       </StackPanel> 
      </Expander.Content>    
     </Expander> 
    </DataTemplate> 

</Window.Resources>