C# WPF Datagrid RowDetailsTemplate 可见性绑定到属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1471534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:53:00  来源:igfitidea点击:

WPF Datagrid RowDetailsTemplate visibility bound to a property

c#.netwpfdatagridwpfdatagrid

提问by WillH

I am using a WPF Datagrid with a RowDetails panel where the RowDetailsVisibilityMode is set to "VisibleWhenSelected" and the SelectionMode="Extended" so that multiple rows can be selected and hence display RowDetails, as below:

我正在使用带有 RowDetails 面板的 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>

Unfortunately, for this application it isn't intuitive to display row details on 'selected' rows, the client would like to click a checkbox on a number of rows to display the RowDetails pane, but also scroll around the grid selecting other rows. In other words fix the rows that display RowDetails no matter what happens on the DataGrid.

不幸的是,对于此应用程序,在“选定”行上显示行详细信息并不直观,客户端希望单击多个行上的复选框以显示 RowDetails 窗格,但还要在网格中滚动选择其他行。换句话说,无论在 DataGrid 上发生什么,都要修复显示 RowDetails 的行。

So currently scrolling around closes the RowDetailsPanes that they have opened. What I would like to do is to have a checkbox in one of the columns and bind the RowDetails panel visibility to this property but I can't figure out how to do it. The problem is simply that RowDetailsPane only operates on the row selection(s) in the datagrid - can it be extended somehow to operate on a property of my choosing?

因此,当前滚动会关闭它们已打开的 RowDetailsPanes。我想要做的是在其中一列中设置一个复选框,并将 RowDetails 面板可见性绑定到此属性,但我不知道该怎么做。问题很简单,RowDetailsPane 仅对数据网格中的行选择进行操作 - 能否以某种方式扩展以对我选择的属性进行操作?

Thanks in advance, Will

提前致谢,威尔

采纳答案by Rory

Looking at the WPF toolkit source code each DataGridRow has a DetailsVisibility property.

查看 WPF 工具包源代码,每个 DataGridRow 都有一个 DetailsVisibility 属性。

I put a button (just for testing) in the first column.

我在第一列放了一个按钮(仅用于测试)。

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

When the button is clicked, find the clicked row and toggle the property.

单击按钮时,找到单击的行并切换属性。

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

I have not explored doing this via databinding.

我还没有探索过通过数据绑定来做到这一点。

回答by Danny Varod

Using pure XAML (+ a converter):

使用纯 XAML(+ 转换器):

XAML:

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

回答by rexall

If you use the (excellent) Lambda Converters library you can save the extra class. This converter uses 2 lambda expressions, the first for Convert, the second for ConvertBack, e.g.:

如果您使用(优秀的)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));

Then the XAML is as follows (note there is no need for StaticResources when using this approach):

那么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 Converters are available here:

Lambda 转换器可在此处获得:

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

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