2009-08-07 10 views
5

Sto utilizzando un datagrid Silverlight 3 e al suo interno sto annidando i record correlati in un altro controllo utilizzando i parametri rowdetails (visibilitymode = visiblewhenselected).Datagrid Silverlight annidato - Dettagli riga funziona alla grande, ma voglio un pulsante!

Mi piace molto come funzioni, ma preferirei che la griglia mostri i dettagli della riga quando viene premuto un pulsante "+", proprio come un albero si espanderà quando si fa clic su un nodo.

ho cercato di definire a livello di codice del modello utilizzando le risorse in questo modo:

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

E nel caso in LoadingRowDetails della griglia, sceglierei il modello da impostare da:

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

Questo sortof lavorate , ma ho scoperto che ho avuto problemi con il crollo del modello di dettagli delle righe precedenti e persino l'arresto anomalo di ie8 (non sono sicuro che sia correlato).

Fondamentalmente, mi piace molto come funziona il datagrid di silverlight 3 e anche come viene implementato il file rowdetailstemplate. Vorrei semplicemente posticipare il caricamento di tutti i dettagli finché una riga non viene espansa di proposito (come sarebbe un albero). Tutte le griglie di terze parti sembrano fare questo, e Microsoft è veramente vicino. Qualcuno ha qualche idea su come risolvere questo?

Grazie, Dennis

risposta

6

Dennis,

Nel caso in cui non si è già trovato una risposta a questo, ho voluto lo stesso comportamento e risolto esso personalizzando il RowHeaderTemplate, che consente di gettare un pulsante l'intestazione per ogni riga. Poi ho implementato un gestore per il pulsante in questo modo:

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

Nota che GetVisualAncestorOfType <> è un metodo di estensione Ho implementato a scavare nella struttura ad albero visuale.

Avrete anche bisogno di impostare la proprietà HeadersVisibility del datagrid per remare o Tutti

+0

Basta chiedersi come vai a deselezionare il ToggleButton sulla riga che viene selezionata quando fai clic sul pulsante di una nuova riga? –

0

vi consiglio di dare un'occhiata all'evento RowVisibilityChanged sulla DataGrid, Fondamentalmente, quando i cambiamenti fila visibilità a "Visible", quindi il carico le informazioni per la riga.

1

qui è un altro modo per ottenere ciò che si sta cercando di fare:

Nel DataGrid istituito un LoadingRow evento come questo:

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

Nel DataGrid creare una colonna modello che conterrà un pulsante come il seguente:

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

nel LoadingRow evento individuare il tasto che è (in questo caso) memorizzato nella prima colonna del DataGrid, quindi memorizzare il cur affittare DataGridRow nell'elemento di pulsanti Tag

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

nei pulsanti di EventHandler (in questo caso ToggleRowDetailsVisibility) estrarremo la riga in modo che possiamo cambiarne lo 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; 
      } 
     } 
    } 

Si noterà che "CurrentlyExpandedRow" , questa è una variabile Globale, di tipo DataGridRow, che memorizziamo la riga attualmente espansa, questo ci permette di chiudere quella Riga quando una nuova deve essere aperta.

Spero che questo aiuti.

1

Oltre alla uxrx risposta fornita qui è il codice per la ricerca di un antenato

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

Per questo:

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

possiamo usare come:

HyperlinkButton button = sender as HyperlinkButton;  
DataGridRow Row = DataGridRow.GetRowContainingElement(button) 
Problemi correlati