2009-09-24 15 views
10

Ich verwende ein WPF Datagrid mit einem RowDetails-Panel, wo der RowDetailsVisibilityMode auf "VisibleWhenSelected" und den SelectionMode = "Extended" festgelegt ist, so dass mehrere Zeilen ausgewählt werden können und RowDetails angezeigt werden unten:WPF Datagrid RowDetailsTemplate Sichtbarkeit an eine Eigenschaft gebunden

<dg:DataGrid x:Name="MyGrid" 
      ItemsSource="{Binding Path=MyItems}" 
      AutoGenerateColumns="True" 
      SelectionMode="Extended" 
      RowDetailsVisibilityMode="VisibleWhenSelected"> 

    <dg:DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <TextBlock Text="Further Details..."/> 
    </DataTemplate> 
    </dg:DataGrid.RowDetailsTemplate> 
    ... 
</dg:DataGrid> 

Leider für diese Anwendung Reihe Details zu ‚ausgewählt‘ Zeilen anzuzeigen es nicht intuitiv ist, würde der Kunde möchte eine Checkbox auf einer Anzahl von Zeilen klicken, um den RowDetails Bereich anzuzeigen, sondern auch Scrollen Sie durch das Raster, indem Sie andere Zeilen auswählen. Mit anderen Worten: Fixieren Sie die Zeilen, die RowDetails anzeigen, unabhängig davon, was auf dem DataGrid passiert.

Das Scrollen umher schließt also die RowDetailsPanes, die sie geöffnet haben. Ich möchte eine Checkbox in einer der Spalten haben und die RowDetails-Panel-Sichtbarkeit an diese Eigenschaft binden, aber ich kann nicht herausfinden, wie es geht. Das Problem ist einfach, dass RowDetailsPane nur auf den Zeilenauswahl (en) im Datagrid funktioniert - kann es irgendwie erweitert werden, um auf einer Eigenschaft meiner Wahl zu operieren?

Vielen Dank im Voraus, Will

Antwort

14

Mit Blick auf dem Toolkit-Quellcode WPF jeden DataGridRow eine DetailsVisibility Eigenschaft hat.

Ich legte eine Schaltfläche (nur zum Testen) in der ersten Spalte.

<toolkit:DataGridTemplateColumn> 
    <toolkit:DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <Button x:Name="buttonDetails" Content="Hello" ButtonBase.Click="Details_Click" /> 
     </DataTemplate> 
    </toolkit:DataGridTemplateColumn.CellTemplate> 
</toolkit:DataGridTemplateColumn> 

Wenn Sie auf die Schaltfläche klicken, suchen Sie die angeklickte Zeile und schalten Sie die Eigenschaft um.

private void Details_Click(object sender, RoutedEventArgs e) 
    { 
     try 
     { 
     // the original source is what was clicked. For example 
     // a button. 
     DependencyObject dep = (DependencyObject)e.OriginalSource; 

     // iteratively traverse the visual tree upwards looking for 
     // the clicked row. 
     while ((dep != null) && !(dep is DataGridRow)) 
     { 
      dep = VisualTreeHelper.GetParent(dep); 
     } 

     // if we found the clicked row 
     if (dep != null && dep is DataGridRow) 
     { 
      // get the row 
      DataGridRow row = (DataGridRow)dep; 

      // change the details visibility 
      if (row.DetailsVisibility == Visibility.Collapsed) 
      { 
      row.DetailsVisibility = Visibility.Visible; 
      } 
      else 
      { 
      row.DetailsVisibility = Visibility.Collapsed; 
      } 
     } 
     } 
     catch (System.Exception) 
     { 
     } 
    } 

Ich habe dies nicht durch Datenbindung erforscht.

+0

Dank Rory, schöne Lösung. Dies ist genau das, was ich wollte, ich war falsch in Bezug auf die Bindung an eine Eigenschaft in meinem ViewModel zu denken, da dies reine View-Funktionalität ist, so dass die Methode, die auf das Click-Ereignis des Kontrollkästchens funktioniert, perfekt ist. – WillH

+2

Dies funktioniert auch für Silverlight, wenn Sie den anfänglichen DataGrid.RowDetailsVisibilityMode = "Collapsed" –

9

Verwendung von reinem XAML (+ einen Konverter):

XAML:

<DataGrid.RowHeaderTemplate> 
    <DataTemplate> 
     <ToggleButton 
      IsChecked="{Binding Path=DetailsVisibility, 
       RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, 
       Converter={StaticResource _VisibilityToNullableBooleanConverter}}" 
      /> 
    </DataTemplate> 
</DataGrid.RowHeaderTemplate> 

Converter:

public class VisibilityToNullableBooleanConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is Visibility) 
     { 
      return (((Visibility)value) == Visibility.Visible); 
     } 
     else 
     { 
      return Binding.DoNothing; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is bool?) 
     { 
      return (((bool?)value) == true ? Visibility.Visible : Visibility.Collapsed); 
     } 
     else if (value is bool) 
     { 
      return (((bool)value) == true ? Visibility.Visible : Visibility.Collapsed); 
     } 
     else 
     { 
      return Binding.DoNothing; 
     } 
    } 
} 
+3

+1 für einen Xaml-Only-Ansatz festlegen, da es einfacher an mehreren Stellen angewendet werden kann und portabler ist, wenn Sie DataGrid Xaml verschieben. –

+0

Das funktioniert gut, wenn Sie den RowDetailsVisibilityMode auf Collapsed festlegen. – user3260977

0

Wenn Sie die (sehr zufrieden) Lambda-Wandler-Bibliothek verwenden können Sie die zusätzliche sparen Klasse. Dieser Konverter arbeitet mit 2 Lambda-Ausdrücke, die erste für Convert, die zweite für ConvertBack, zB:

public static readonly IValueConverter VisibilityToBoolean = 
     ValueConverter.Create<Visibility, bool>(
     (e => e.Value == Visibility.Visible), 
      (e => e.Value ? Visibility.Visible : Visibility.Collapsed)); 

Dann ist die XAML wie folgt (beachten Sie, dass für StaticResources nicht erforderlich ist, wenn mit diesem Ansatz):

 <DataGrid.RowHeaderTemplate> 
      <DataTemplate> 
       <ToggleButton> 
        <ToggleButton.IsChecked> 
         <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridRow}}" Path="DetailsVisibility" 
           Converter="{x:Static lc40:Converters.VisibilityToBoolean}"/> 
        </ToggleButton.IsChecked> 
       </ToggleButton> 
      </DataTemplate> 
     </DataGrid.RowHeaderTemplate> 

Lambda-Wandler sind hier verfügbar:

https://github.com/michael-damatov/lambda-converters

Verwandte Themen