2009-08-07 5 views
5

Ich benutze ein Silverlight 3 Datagrid, und innerhalb dieser verschachtelte ich verwandte Datensätze in einem anderen Steuerelement mithilfe der RowDetails (VisibilityMode = Visiblewhenselected).Nested Silverlight Datagrid - Row Details funktioniert gut, aber ich möchte eine Schaltfläche!

Ich mag wirklich, wie das funktioniert, aber ich würde viel lieber das Raster die Zeilendetails anzeigen, wenn eine "+" Schaltfläche gedrückt wird, ähnlich wie eine Struktur erweitert wird, wenn Sie auf einen Knoten klicken.

Ich habe versucht, programmatisch die Vorlage definieren, indem sie Ressourcen wie folgt aus:

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

und in der LoadingRowDetails Veranstaltung Gitter, würde ich wählen, welche Vorlage eingestellt von:

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

Diese sortof gearbeitete , aber ich habe festgestellt, dass ich Probleme mit dem Kollabieren von vorherigen Zeilen Detailvorlage hatte, und stürzte sogar ie8 (nicht sicher, ob das verwandt ist).

Grundsätzlich mag ich wirklich, wie das Silverlight 3 Datagrid funktioniert, und sogar wie das rowdetemplated Zeug implementiert ist. Ich möchte einfach das Laden von Details verzögern, bis eine Zeile absichtlich erweitert wird (wie ein Baum wäre). Alle Gitter von Drittanbietern scheinen dies zu tun, und Microsofts ist so nah. Hat jemand eine Idee, wie man das löst?

Danke, Dennis

Antwort

6

Dennis,

Falls Sie nicht bereits eine Antwort auf diese gefunden, wollte ich das gleiche Verhalten und löste es durch die RowHeaderTemplate Customizing, die Sie auf eine Schaltfläche werfen lässt in die Kopfzeile für jede Zeile. Dann implementiert ich einen Handler für die Schaltfläche wie folgt:

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

Beachten Sie, dass GetVisualAncestorOfType <> ist eine Erweiterung Methode, die ich umgesetzt habe in der visuellen Struktur zu graben.

Sie werden auch die Datagrid festlegen müssen HeadersVisibility Eigenschaft auf Zeile oder alle

+0

Nur frage mich, wie Sie deaktivieren den ToggleButton in der Zeile, die ausgewählt ist, wenn Sie auf die Schaltfläche einer neuen Zeile klicken? –

0

Ich schlage vor, Sie nehmen einen Blick auf die RowVisibilityChanged Ereignis auf dem Datagrid, im Grunde, wenn die Zeile Sichtbarkeit ändert sich auf „Sichtbar“, dann laden die Info für die Reihe.

1

hier ist eine andere Art und Weise zu erreichen, was Sie zu tun versuchen:

In dem Datagrid eine LoadingRow Ereignis wie folgt aufgebaut:

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

In dem Datagrid eine Vorlagenspalte erstellen, die eine enthält Taste wie die folgenden:

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

im LoadingRow Ereignisse die Taste lokalisiert, die (in diesem Fall) in der ersten Spalte des Datenraster gespeichert ist, dann speichert die CUR mieten DataGridRow in die Tasten Tag Element

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

In den Buttons Eventhandler (in diesem Fall ToggleRowDetailsVisibility) werden wir die Reihe extrahieren, so dass wir hin- und herschalten seine 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; 
      } 
     } 
    } 

Sie werden feststellen, dass "CurrentlyExpandedRow" Dies ist eine globale Variable vom Typ DataGridRow, in der wir die aktuell erweiterte Zeile speichern. Dadurch können wir diese Zeile schließen, wenn eine neue Zeile geöffnet werden soll.

Hoffe, das hilft.

1

Neben der Antwort uxrx hier vorgesehen ist der Code für die Suche nach einen Vorfahren

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

Dazu:

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

Wir können als verwenden:

HyperlinkButton button = sender as HyperlinkButton;  
DataGridRow Row = DataGridRow.GetRowContainingElement(button) 
Verwandte Themen