WPF中DataGrid的行详细信息模板可通过绑定属性控制其可见性。

11

我正在使用 WPF Datagrid,其中 RowDetailsVisibilityMode 被设置为 "VisibleWhenSelected",SelectionMode="Extended" 以便可以选择多行并显示 RowDetails,如下:

<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>
很不幸,对于这个应用程序,要在“选定的”行上显示行详细信息并不直观。客户希望单击多行复选框以显示RowDetails窗格,但也可以在网格中滚动选择其他行。换句话说,无论在DataGrid上发生什么情况,都要固定显示RowDetails的行。

因此,目前在网格中滚动会关闭他们打开的RowDetailsPanes。我想做的是在其中一列中放置一个复选框,并将RowDetails面板可见性绑定到此属性,但我不知道如何实现。问题很简单,即RowDetailsPane只操作数据网格中的行选择 - 是否有办法将其扩展以操作我选择的属性?

提前感谢, Will
3个回答

14

查看WPF工具包源代码可以发现每个DataGridRow都有一个DetailsVisibility属性。

我在第一列中放置了一个按钮(仅供测试)。

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

当按钮被点击时,查找被点击的行并切换属性。

   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)
      {
      }
    }

我尚未探索通过数据绑定实现此操作。


谢谢Rory,好的解决方案。这正是我想要的,我之前错误地认为需要绑定到ViewModel中的属性,但实际上这完全是View功能,所以在复选框的单击事件上操作的方法是完美的。 - WillH
2
如果您将初始的DataGrid.RowDetailsVisibilityMode设置为“Collapsed”,则这也适用于Silverlight。 - Michael S. Scherotter

10

使用纯XAML(加一个转换器):

XAML:

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

转换器:

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

4
+1 支持仅使用 Xaml 方法,因为这样更容易在多个地方应用,并且在移动 DataGrid Xaml 时更具可移植性。 - Jason Frank
当您将RowDetailsVisibilityMode设置为Collapsed时,这将很好地运作。 - user3260977

0
如果您使用(优秀的)Lambda Converters库,您可以节省额外的类。该转换器使用2个lambda表达式,第一个用于Convert,第二个用于ConvertBack,例如:
    public static readonly IValueConverter VisibilityToBoolean =
        ValueConverter.Create<Visibility, bool>(
        (e => e.Value == Visibility.Visible),
            (e => e.Value ? Visibility.Visible : Visibility.Collapsed));

然后,XAML 如下(请注意,使用此方法时无需使用 StaticResources):

     <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转换器:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接