2009-08-14 3 views
0

J'ai rencontré un problème lors de la tentative de recherche d'un élément déclaré dans DataTemplate, qui a ensuite été appliqué comme un objet ContentTemplate à TabItem. J'ai vu qu'il y a déjà quelques solutions concernant ce problème, mais aucune d'entre elles ne fonctionne réellement dans mon cas, et je voudrais comprendre pourquoi (évidemment je fais erreur à un endroit) Voici un exemple de code:Rechercher un élément dans DataTemplate appliqué à TabItem

<DataTemplate x:Key="TabItemDataTemplate">    
    <Grid HorizontalAlignment="Stretch" 
     VerticalAlignment="Stretch" Name="templateGrid"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="6.0*"> </RowDefinition> 
      <RowDefinition Height="6" ></RowDefinition> 
      <RowDefinition Height="6.0*" ></RowDefinition> 
      <RowDefinition Height="*" ></RowDefinition> 
     </Grid.RowDefinitions>     

     <ListView x:Name="repoView" Grid.Row="0" 
      VerticalAlignment="Stretch" 
      ItemsSource="{Binding Source={StaticResource DataProviderForListView}}">       
      <GridView> 
       <GridViewColumn Header="State" 
        DisplayMemberBinding="{Binding Path=RepositoryItemState}"/> 
       <GridViewColumn Header="Working Copy Rev num." 
        DisplayMemberBinding="{Binding Path=WCRevision}"/> 
       <GridViewColumn Header="Repository Rev num." 
        DisplayMemberBinding="{Binding Path=RepoRevision}"/> 
       <GridViewColumn Header="User" 
        DisplayMemberBinding="{Binding Path=Account}"/> 
       <GridViewColumn Header="Item" 
        DisplayMemberBinding="{Binding Path=ItemName}"/> 
      </GridView> 
     </ListView> 

     <GridSplitter x:Name="gridSplitter" Grid.Row="1" 
      ResizeDirection="Rows" Background="Gray" 
      Height="4" HorizontalAlignment="Stretch" 
      Style="{StaticResource gridSplitterStyle}"/> 

     <RichTextBox x:Name="rowView" Grid.Row="2" 
      BorderBrush="Bisque" VerticalAlignment="Stretch" 
      IsReadOnly="True" Background="YellowGreen" 
      FontFamily="Comic Sans Serif"/> 


     <ToggleButton x:Name="rbWorkingCopy" 
      Template="{StaticResource ToggleButtonControlTemplate}" 
      Grid.Row="3" Width="100" Height="22" 
      Content="{StaticResource WorkingCopyTitle}" 
      HorizontalAlignment="Left" VerticalAlignment="Bottom" 
      Command="repoManager:AppCommands.GetWorkingCopyInfoCommand" /> 
     <ToggleButton x:Name="rbRepository" 
      Template="{StaticResource ToggleButtonControlTemplate}" 
      Grid.Row="3" Width="100" Height="22" 
      Content="{StaticResource RepositoryTitle}" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Bottom" Margin="120,0,0,0" 
      Command="repoManager:AppCommands.GetRepoInfoCommand" /> 
     <ProgressBar x:Name="checkRepositoryProgress" Grid.Row="3" 
      Width="220" Height="22" HorizontalAlignment="Right" 
      VerticalAlignment="Bottom" Margin="250,0,10,0" 
      IsIndeterminate="True" 
      IsEnabled="{Binding repoManager:ExecutingCommand}" /> 
    </Grid> 
</DataTemplate> 

Ce code est porgrammatically appliqué à l'objet TabItem donné de la manière suivante:

this.ContentTemplate = FindResource("TabItemDataTemplate") as DataTemplate; 

Après avoir besoin d'un accès à l'élément ListView déclaré dans DataTemplate, donc j'exécuter les codes trouvés autour dans Internet, et aussi sur ce site. Voici un court exemple:

/* Getting the ContentPresenter of myListBoxItem*/   
ContentPresenter myContentPresenter = 
    FindVisualChild<ContentPresenter>(this); 

// this.GetVisualChild(0) 
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/ 
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate; 

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter); 

problème1: Dans ce cas ContentTemplate de ContentPresenter est nul, si les accidents d'exécution de code. Prolem2: D'accord, je pense, peut-être que je dois naviguer jeter le contenu de TabItem directement, de sorte que le code devient plus ou moins:

/* Getting the ContentPresenter of myListBoxItem*/   
ContentPresenter myContentPresenter = 
    FindVisualChild<ContentPresenter>(this); 

// this.GetVisualChild(0) 
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/ 
DataTemplate myDataTemplate = this.ContentTemplate; 

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter); 

ce est l'objet TabItem. Mais les choses de strage, que le ContentTemplate de ce est complètement différent de celui assigné ci-dessus. Je suis sûr que j'ai raté quelque chose quelque part, pouvez-vous m'aider à comprendre le problème? Merci.

Répondre

0

Ok, on y arrive :) Je résous le problème, de manière pas très sympa, mais il semble que cela fonctionne correctement. Comme je l'ai mentionné ci-dessus, j'ai utilisé la méthode LoadContent et elle me renvoie l'objet ListView, mais d'ailleurs ce n'était pas ListView que l'interface utilisateur utilise réellement. Donc pour résoudre ce problème, j'ajoute une propriété statique pour contenir mon objet REAL ListView (statique car j'ai DataTemplate unique qui contient ListView partagé sur plusieurs TabItems, donc le ListView partagé aussi) et ajoute un gestionnaire d'événement à mon DataTemplate ->Loaded. Attraper cet événement, qui dans mon cas soulève seulement ceux dans la vie de l'application, dans RoutedEventOriginalSource J'ai l'objet REAL ListView que le moteur WPF utilise pour le rendu sur l'interface utilisateur. J'espère que ma solution aidera quelqu'un. Merci à tous.

0

Vous ne souhaitez pas utiliser les propriétés de modèle du TabItem, car celles-ci sont utilisées pour créer les contrôles réels plutôt que de les stocker. Vous devriez être capable de rechercher directement dans l'arborescence ListView plutôt que de passer par le DataTemplate.

+0

Bien sûr.Je "résoudre", peut-être, ce problème, en appelant au moment de l'affectation de ControlTemplate LoadContent(), que dans mon cas particulier renvoie la grille, c'est la racine de mon DataTemplate. Ma confusion était, pourquoi le ContentPresenter ne contient rien? Dans les exemples de codes trouvés sur Internet, aucune déclaration ContentPresenter explicite n'a été trouvée dans DataTemplate. A la fin, je change un peu ma structure de code, afin d'accéder aux données dont j'ai besoin d'autres façons, mon être aussi plus simple :), d'ailleurs jusqu'à maintenant je n'ai pas trouvé la résolution de ce genre de problème. – Tigran

+0

Une chose que j'ai remarquée, en naviguant jeter les exemples de codes, qu'ils appliquent généralement le DataTemplate de l'élément parent à l'élément. J'ai donc essayé d'appliquer la propriété ItemTemplate de TabControl (même si ce n'est pas pratique pour cette application, mais juste pour essayer de comprendre le problème), mais cela n'a pas fonctionné. – Tigran

0

Simplement, si vous avez un DataGrid, et un TemplateColumn qui contient un modèle de données, vous pouvez utiliser l'exemple de code suivant:

<DataGridTemplateColumn x:Name="photoPathColumn" Header="{x:Static resx:FrmResource.Photo}" Width="Auto"> 
    <DataGridTemplateColumn.CellEditingTemplate x:Uid="keyelm"> 
     <DataTemplate x:Name="dodo"> 
      <StackPanel Orientation="Horizontal" Height="Auto"> 
       <TextBlock x:Name="photo" x:Uid="imageFile" Text="{Binding Path=PhotoPath}"></TextBlock> 
       <Button x:Name="Browse" Content="..." Click="Browse_Click"></Button> 
      </StackPanel> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellEditingTemplate> 

TextBlock tBlock = (TextBlok)photoPathColumn.CellEditingTemplate.FindName(
         "photo", 
         photoPathColumn.GetCellContent(CustomersDataGrid.CurrentItem)); 
  • photo est le nom du bloc de texte
  • photoPathColumn est le DataGridTemplateColumn.
+1

Il déclenche une exception. – Shimmy

Questions connexes