2009-08-07 3 views
5

J'utilise une grille de données silverlight 3, et à l'intérieur de celle-ci, j'imprime des enregistrements associés dans un autre contrôle en utilisant les détails de ligne (visibilitymode = visiblewhenselected). J'aime vraiment comment cela fonctionne, mais je préfère que la grille affiche les détails de la ligne quand un bouton "+" est pressé, tout comme un arbre se développera lorsque vous cliquez sur un nœud.Datagrid imbriqué Silverlight - Row Détails fonctionne très bien, mais je veux un bouton!

J'ai essayé de définir par programme le modèle en utilisant des ressources comme celui-ci:

<Grid.Resources> 
    <DataTemplate x:Key="EmptyTemplate"> 
     <StackPanel> 
      <!--<TextBlock Text="Empty Template!!!" />--> 
     </StackPanel> 
    </DataTemplate> 
    <DataTemplate x:Key="SongTemplate"> 
     <StackPanel> 
      <AdminControls:ArtistSongControl x:Name="ArtistSongControl" /> 
     </Stack> 
    </DataTemplate> 
</Grid.Resources> 

Et dans le cas de LoadingRowDetails de la grille, je choisirais quel modèle défini par:

e.Row.DetailsTemplate = (DataTemplate)LayoutRoot.Resources["SongTemplate"]; 

Ce sortof travaillé , mais j'ai trouvé que j'avais des problèmes avec l'effondrement du modèle de détails des lignes précédentes, et même s'est écrasé ie8 (pas sûr si c'est lié).

Fondamentalement, j'aime vraiment comment fonctionne la grille de données silverlight 3, et même comment la substance rowdetailstemplate est implémentée. Je voudrais simplement différer le chargement de tous les détails jusqu'à ce qu'une rangée soit étendue intentionnellement (comme le ferait un arbre). Toutes les grilles de 3ème partie semblent faire cela, et microsoft est si proche. Est-ce que quelqu'un a une idée de comment résoudre celui-ci?

Merci, Dennis

Répondre

6

Dennis,

Si vous ne l'avez pas déjà trouvé une réponse à cela, je voulais le même comportement et résolu en personnalisant le RowHeaderTemplate, qui vous permet de jeter un bouton l'en-tête pour chaque rangée. Ensuite, je mis en place un gestionnaire pour le bouton comme ceci:

private void ToggleButton_Click(object sender, System.Windows.RoutedEventArgs e) 
{ 
    ToggleButton button = sender as ToggleButton; 
    DataGridRow row = button.GetVisualAncestorOfType<DataGridRow>(); 

    if (button.IsChecked == true) 
    { 
     row.DetailsVisibility = Visibility.Visible; 

     //Hide any already expanded row. We only want one expanded at a time for simplicity and 
     //because it masks a virtualization bug in the datagrid. 
     if (_expandedRow != null) 
      _expandedRow.DetailsVisibility = Visibility.Collapsed; 

     _expandedRow = row; 
    } 
    else 
    { 
     row.DetailsVisibility = Visibility.Collapsed; 
     _expandedRow = null; 
    } 
} 

Notez que GetVisualAncestorOfType <> est une méthode d'extension que j'ai mis à creuser dans l'arbre visuel.

Vous devez également définir je vous suggère de prendre la propriété de DataGrid HeadersVisibility à la rangée ou tous

+0

Je me demandais comment vous allez désactiver le ToggleButton sur la ligne qui est sélectionnée lorsque vous cliquez sur le bouton d'une nouvelle ligne? –

0

un coup d'oeil à l'événement RowVisibilityChanged sur la grille de données, essentiellement lorsque les changements de visibilité de la ligne à « visible », puis charge l'info pour la rangée.

1

ici est une autre façon d'obtenir ce que vous essayez de faire:

Dans le DataGrid mis en place un événement LoadingRow comme ceci:

<data:DataGrid LoadingRow="ItemsGrid_LoadingRow" ..... 

Dans le DataGrid créer une colonne de modèle qui contiendra un bouton comme le suivant:

<data:DataGridTemplateColumn CellStyle="{StaticResource DataGridCellStyle1}" CanUserReorder="False"> 
     <data:DataGridTemplateColumn.CellTemplate> 
      <DataTemplate> 
        <Button x:Name="ViewButton" Click="ToggleRowDetailsVisibility" Cursor="Hand" Content="View Details" />          
      </DataTemplate> 
     </data:DataGridTemplateColumn.CellTemplate> 
     </data:DataGridTemplateColumn> 

en cas LoadingRow trouver le bouton qui est (dans ce cas) stocké dans la première colonne du DataGrid, puis stocker le cabot louer DataGridRow dans les boutons élément Tag

private void ItemsGrid_LoadingRow(object sender, DataGridRowEventArgs e) 
    { 
     var ViewButton = (Button)ItemsGrid.Columns[0].GetCellContent(e.Row).FindName("ViewButton"); 
     ViewButton.Tag = e.Row; 
    } 

Dans les boutons eventHandler (dans ce cas ToggleRowDetailsVisibility) nous extraire la ligne afin que nous puissions passer son DetailsVisibility

In the LoadingRow Event locate the button that is (in this case) stored in the first column of the DataGrid, then store the current DataGridRow into the buttons Tag element 

private void ToggleRowDetailsVisibility(object sender, RoutedEventArgs e) 
    { 
     var Button = sender as Button; 
     var Row = Button.Tag as DataGridRow; 

     if(Row != null) 
     { 
      if(Row.DetailsVisibility == Visibility.Collapsed) 
      { 
       Row.DetailsVisibility = Visibility.Visible; 

       //Hide any already expanded row. We only want one expanded at a time for simplicity and 
       //because it masks a virtualization bug in the datagrid. 
       if (CurrentlyExpandedRow != null) 
       { 
        CurrentlyExpandedRow.DetailsVisibility = Visibility.Collapsed; 
       } 

       CurrentlyExpandedRow = Row; 
      } 
      else 
      { 
       Row.DetailsVisibility = Visibility.Collapsed; 
       CurrentlyExpandedRow = null; 
      } 
     } 
    } 

Vous remarquerez que « CurrentlyExpandedRow » , il s'agit d'une variable globale, de type DataGridRow, dans laquelle nous stockons la ligne actuellement développée, ceci nous permet de fermer cette ligne quand une nouvelle doit être ouverte.

Espérons que cela aide.

1

En plus de la uxrx de réponse fournie ici est le code pour trouver un ancêtre

public static partial class Extensions 
{ 
    public static T FindAncestor<T>(DependencyObject obj) where T : DependencyObject 
    { 
     while (obj != null) 
     { 
      T o = obj as T; 
      if (o != null)    
       return o; 

      obj = VisualTreeHelper.GetParent(obj); 
     } 
     return null; 
    } 

    public static T FindAncestor<T>(this UIElement obj) where T : UIElement 
    { 
     return FindAncestor<T>((DependencyObject)obj); 
    } 
} 
1

Pour cela:

DataGridRow row = button.GetVisualAncestorOfType<DataGridRow>(); 

Nous pouvons utiliser comme:

HyperlinkButton button = sender as HyperlinkButton;  
DataGridRow Row = DataGridRow.GetRowContainingElement(button) 
Questions connexes