2009-08-07 9 views
5

Estoy usando una cuadrícula de datos silverlight 3, y dentro de ella, estoy anidando registros relacionados en otro control usando los detalles de fila (visibilitymode = visible cuando se selecciona).Datagrid plateado anidado - Detalles de fila funciona muy bien, pero quiero un botón!

Me gusta mucho cómo funciona esto, pero prefiero que la grilla muestre los detalles de la fila cuando se presiona el botón "+", del mismo modo que un árbol se expandirá al hacer clic en un nodo.

he intentado definir mediante programación la plantilla mediante el uso de los recursos de esta manera:

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

Y en caso LoadingRowDetails de la red, me quedaría con qué plantilla para ajustar por:

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

Este sortof trabajados , pero encontré que tuve problemas para colapsar la plantilla de detalles de las filas anteriores, e incluso se colgó ie8 (no estoy seguro si eso está relacionado).

Básicamente, realmente me gusta cómo funciona la cuadrícula de datos de Silverlight 3, e incluso cómo se implementa el material de la plantilla rowdetails. Simplemente me gustaría diferir la carga de cualquier detalle hasta que una fila se expanda deliberadamente (como lo haría un árbol). Todas las cuadrículas de terceros parecen hacer esto, y Microsoft está tan cerca. ¿Alguien tiene alguna idea de cómo resolver este?

Gracias, Dennis

Respuesta

6

Dennis,

En caso de que no lo ha encontrado una respuesta a esto, yo quería el mismo comportamiento y lo resolvieron mediante la personalización de la RowHeaderTemplate, que le permite lanzar un botón de el encabezado de cada fila A continuación, he implementado un controlador para el botón de este 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; 
    } 
} 

Tenga en cuenta que GetVisualAncestorOfType <> es un método de extensión He aplicado a cavar en el árbol visual.

También tendrá que establecer la propiedad HeadersVisibility de la cuadrícula de datos a la fila o Todos

+0

Sólo me preguntaba cómo ¿Desea anular la selección de ToggleButton en la fila que se selecciona al hacer clic en el botón de una nueva fila? –

0

sugiero que eche un vistazo en el evento RowVisibilityChanged en la cuadrícula de datos, básicamente cuando los cambios de visibilidad fila en "visible", entonces la carga la información para la fila

1

aquí es otra manera de lograr lo que estamos tratando de hacer:

En la cuadrícula de datos configurar un evento LoadingRow así:

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

En la cuadrícula de datos crea una columna plantilla que contenga una botón tales como los siguientes:

<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 el evento LoadingRow localizar el botón que es (en este caso) se almacena en la primera columna de la cuadrícula de datos, a continuación, almacenar el cur alquilar DataGridRow en el elemento de botones Tag

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

En los botones de manejador de sucesos (en este caso ToggleRowDetailsVisibility) vamos a extraer la fila para que podamos cambiar su 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; 
      } 
     } 
    } 

Usted se dará cuenta de que "CurrentlyExpandedRow" , esta es una variable Global, de tipo DataGridRow, en la que almacenamos la fila actualmente expandida, esto nos permite cerrar esa Fila cuando se abra una nueva.

Espero que esto ayude.

1

Además de la uxrx respuesta proporcionada aquí es el código para encontrar un antepasado

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

Por esta:

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

podemos utilizar como:

HyperlinkButton button = sender as HyperlinkButton;  
DataGridRow Row = DataGridRow.GetRowContainingElement(button) 
Cuestiones relacionadas