2009-12-28 3 views
3

J'ai une zone de liste qui affiche les résultats d'une requête TFS. Je souhaite modifier le style de ListBoxItem dans le code pour avoir les colonnes qui sont incluses dans les résultats de la requête.WPF - Modifier un style dans le code derrière

Le style de ListBoxItem est défini dans ma section Windows.Resoruces. J'ai essayé ceci:

public T GetQueryResultsElement<T>(string name) where T : DependencyObject 
{ 
    ListBoxItem myListBoxItem = 
     (ListBoxItem)(lstQueryResults.ItemContainerGenerator.ContainerFromIndex(0)); 

    // Getting the ContentPresenter of myListBoxItem 
    ContentPresenter myContentPresenter = 
     myListBoxItem.Template.LoadContent().FindVisualChild<ContentPresenter>(); 

    // Finding textBlock from the DataTemplate that is set on that ContentPresenter 
    DataTemplate myDataTemplate = myContentPresenter.ContentTemplate; <------+ 
    T myControl = (T)myDataTemplate.FindName(name, myContentPresenter);  | 
                       |  
    return (T)myControl;              | 
}                    | 
                       | 
     ContentTemplate is null ----------------------------------------------+ 

Mais ContentTemplate est null. J'ai obtenu ce code de here, puis l'a modifié avec l'appel LoadContent (le code original a donné null pour ContentPresenter).

Quoi qu'il en soit. Si vous connaissez un moyen de changer un style existant dans le code, j'aimerais le voir.


Specifics si vous voulez les:
Je vais pour WrapPanel dans mon ListBoxItem style. C'est ce que je veux ajouter aux éléments TextBlock supplémentaires.

Voici une partie de mon style:

<!--Checkbox ListBox--> 
<Style x:Key="CheckBoxListStyle" TargetType="ListBox"> 
    <Style.Resources> 
     <Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem"> 
      <Setter Property="Tag" Value="{Binding Id}"/> 
      <Setter Property="Background"> 
       <Setter.Value> 
        <Binding Path="Type" Converter="{StaticResource WorkItemTypeToColorConverter}" /> 
       </Setter.Value> 
      </Setter> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="ListBoxItem"> 
         <Border BorderThickness="1" BorderBrush="#D4D4FF"> 
          <Grid Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WrapPanel}}, Path=ActualWidth}" ScrollViewer.CanContentScroll="True" Margin="2"> 
           <Grid.ColumnDefinitions> 
            <ColumnDefinition Width="20" /> 
            <ColumnDefinition Width="*" /> 
            <ColumnDefinition Width="30" /> 
           </Grid.ColumnDefinitions> 
           <Grid.Background> 
            <Binding Path="Type" Converter="{StaticResource WorkItemTypeToColorConverter}" /> 
           </Grid.Background> 

           <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding IsSelected, 
             RelativeSource={RelativeSource TemplatedParent}, 
             Mode=TwoWay}" Name="chkIsSelected" /> 
           <WrapPanel Grid.Column="1" Margin="5,0,5,0" Name="QueryColumns"> 
            <TextBlock VerticalAlignment="Center" Text="{Binding Id}" Name="txtID" /> 
            <TextBlock VerticalAlignment="Center" Margin="5,0,5,0" Text="{Binding Title}" Name="txtTitle" /> 
           </WrapPanel> 

Répondre

11

Vous allez contre le grain ici, en essayant de manipuler des éléments visuels directement dans le code-behind. Il existe une solution très simple impliquant la liaison de données.

Je vais fournir la solution générale parce que je ne connais pas les détails de votre solution.

Une fois que vous obtenez les résultats de votre requête, créez une énumération qui retourne un nom de colonne et une valeur de champ pour chaque itération.

Exemple:

class NameValuePair 
{ 
    public string Name { get; set; } 
    public object Value { get; set; } 
} 

public IEnumerable<IEnumerable<NameValuePair>> EnumerateResultSet(DataTable resultSet) 
{ 
    foreach (DataRow row in resultSet.Rows) 
     yield return EnumerateColumns(resultSet, row); 
} 

public IEnumerable<NameValuePair> EnumerateColumns(DataTable resultSet, DataRow row) 
{ 
    foreach (DataColumn column in resultSet.Columns) 
     yield return new NameValuePair 
      { Name = column.ColumnName, Value = row[column] }; 
} 

Et dans votre code-behind, une fois que vous obtenez votre jeu de résultats DataTable, faites ceci:

myResultsList.ItemsSource = EnumerateResultSet(myDataTable); 

Le XAML pourrait ressembler à ceci:

<Window.Resources> 
    <DataTemplate x:Key="ColumnTemplate"> 
     <Border BorderBrush="Black" BorderThickness="1" CornerRadius="2" Padding="2"> 
      <WrapPanel> 
       <TextBlock Text="{Binding Name}" Margin="0,0,5,0"/> 
       <TextBlock Text="{Binding Value}" Margin="0,0,10,0"/> 
      </WrapPanel> 
     </Border> 
    </DataTemplate> 
    <DataTemplate x:Key="RowTemplate"> 
     <Grid> 
      <ItemsControl 
       ItemsSource="{Binding}" 
       ItemTemplate="{StaticResource ColumnTemplate}" 
       Margin="0,5,0,5"/> 
     </Grid> 
    </DataTemplate> 
</Window.Resources> 
<Grid> 
    <ListBox Name="myResultsList" ItemTemplate="{StaticResource RowTemplate}"/> 
</Grid> 

Exemple de sortie:

Sample Output Image

+1

Cela a très bien fonctionné! Quoi de plus, c'est une réponse fantastique. Je l'ai défini comme réponse, mais je ne peux pas l'augmenter en raison d'un problème avec Stack Overflow. Je l'ai soumis comme un bug sur meta: http://meta.stackexchange.com/questions/34009/cant-upvote-an-answer-says-the-vote-it-too-old Merci beaucoup d'avoir pris la le temps de m'aider avec ça. WPF est génial quand vous le faites de la bonne façon, mais c'est quand vous êtes sur le mauvais chemin. Merci de m'avoir montré le chemin ... – Vaccano

+0

Vous avez raison sur votre dernière déclaration :) Et vous êtes les bienvenus! –

Questions connexes