XAML 单击DataGrid行中自定义边框内的空白区域时不触发SelectionChanged事件

h7wcgrx3  于 2023-08-01  发布在  其他
关注(0)|答案(1)|浏览(96)

下面是DataGridSamplePage.xaml

<Page x:Class="SampleWpf.DataGridSamplePage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800"
  Title="DataGridSamplePage">
<Page.Resources>
    <Style x:Key="CustomDataGridRowStyle"
           TargetType="DataGridRow">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridRow">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            Background="LightGray"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="20"
                            Margin="0,5,0,5">
                        <SelectiveScrollingGrid>
                            <SelectiveScrollingGrid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*" />
                            </SelectiveScrollingGrid.ColumnDefinitions>
                            <SelectiveScrollingGrid.RowDefinitions>
                                <RowDefinition Height="*" />
                                <RowDefinition Height="Auto" />
                            </SelectiveScrollingGrid.RowDefinitions>
                            <DataGridCellsPresenter Grid.Column="1"
                                                    ItemsPanel="{TemplateBinding ItemsControl.ItemsPanel}"
                                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            <DataGridDetailsPresenter Grid.Column="1"
                                                      Grid.Row="1"
                                                      Visibility="{TemplateBinding DataGridRow.DetailsVisibility}"
                                                      SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                            <DataGridRowHeader Grid.RowSpan="2"
                                               SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                               Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                        </SelectiveScrollingGrid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>
<Grid>
    <DataGrid 
              x:Name="MyDataGrid"
              SelectionChanged="MyDataGrid_OnSelectionChanged"
              Margin="20"
              Grid.Row="0"
              Background="Transparent"
              BorderThickness="0"
              FontSize="18"
              RowHeight="80"
              SelectionUnit="FullRow"
              CanUserResizeRows="False"
              IsReadOnly="True"
              VirtualizingStackPanel.IsVirtualizing="True"
              CanUserSortColumns="False"
              CanUserReorderColumns="False"
              CanUserResizeColumns="False"
              GridLinesVisibility="None"
              HorizontalScrollBarVisibility="Hidden"
              VerticalScrollBarVisibility="Hidden"
              SelectionMode="Single"
              FontWeight="Bold"
              AutoGenerateColumns="False"
              HeadersVisibility="Column"
              ColumnWidth="Auto"
              VerticalGridLinesBrush="Transparent"
              Height="Auto"
              HorizontalAlignment="Left"
              VerticalAlignment="Stretch"
              Width="Auto">
        <DataGrid.ColumnHeaderStyle>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="Background"
                        Value="Transparent" />
                <Setter Property="HorizontalContentAlignment"
                        Value="Center" />
                <Setter Property="Padding"
                        Value="15" />
            </Style>
        </DataGrid.ColumnHeaderStyle>
        <DataGrid.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Setter Property="Padding"
                        Value="20" />
                <Setter Property="VerticalAlignment"
                        Value="Center" />
                <Setter Property="HorizontalAlignment"
                        Value="Center" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridCell}">
                            <Border BorderThickness="0"
                                    Padding="5">
                                <ContentPresenter />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.CellStyle>
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow"
                   BasedOn="{StaticResource CustomDataGridRowStyle}" />
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id"
                                Binding="{Binding Id}" />
            <DataGridTextColumn Header="PatientId"
                                Binding="{Binding PatientId}" />
            <DataGridTextColumn Header="DoctorId"
                                Binding="{Binding DoctorId}" />
            <DataGridTextColumn Header="Location"
                                Binding="{Binding Location}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

字符串
下面是我的DataGridSamplePage.xaml.cs

public partial class DataGridSamplePage : Page
{
    public DataGridSamplePage()
    {
        InitializeComponent();

        List<Appointment> list = new();

        for (int i = 1; i <= 6; i++)
        {
            var appointment = new Appointment
            {
                Id = "i",
                PatientId = $"P{i}",
                DoctorId = $"D{i}",
                Location = $"Location {i}"
            };
            list.Add(appointment);
        }

        MyDataGrid.ItemsSource = list;
    }

    private void MyDataGrid_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Debug.WriteLine("MyDataGrid_OnSelectionChanged fired");
    }
}

public class Appointment
{
    public string Id { get; set; }

    public string PatientId { get; set; } 
    public string DoctorId { get; set; }  
    public string Location { get; set; }

}


我有一个带有DataGrid的WPF应用程序,它使用自定义行样式。此样式包含边框元素。我的问题是,当我单击一行的Border元素中的空白区域时,DataGrid的SelectionChanged事件不会被触发。仅当我直接单击单元格中的文本时,才会触发该事件。我希望在单击行边框内的任意位置时触发该事件。我如何才能做到这一点?

9nvpjoqh

9nvpjoqh1#

首先,您必须通过将背景Brush分配给DataGridCell模板的根Border来提供命中测试图面。您通常会将Border.Background绑定到模板化父级的Background属性。
其次,必须允许内容拉伸以占据可用单元格的空间。目前,由于HorizontalAlignmentVerticalAlignment被设置为Center,因此单元格内容将只占用最小的空间。因此,将HorizontalContentAlignmentVerticalContentAlignment设置为中心,并将HorizontalAlignmentVerticalAlignment设置为Stretch。由于您要覆盖ControlTemplate,因此必须将HorizontalContentAlignmentVerticalContentAlignmentHorizontalContentAlignmentVerticalContentAlignment绑定到ContentPresenter,以使内容对齐生效。
此外,还必须将其他布局属性连接到模板化父级。例如,您将Padding设置为20,但当前此值不会传播到实际布局/ControlTemplate,因为Padding属性与内容布局断开连接。
DataGridCell的固定Style可以如下所示:

<DataGrid.CellStyle>
  <Style TargetType="{x:Type DataGridCell}">
    <Setter Property="Padding"
            Value="20" />
    <Setter Property="BorderThickness"
            Value="0" />
    <Setter Property="VerticalContentAlignment"
            Value="Center" />
    <Setter Property="HorizontalContentAlignment"
            Value="Center" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridCell}">
          <Border BorderThickness="{TemplateBinding BorderThickness}"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  Padding="{TemplateBinding Padding}">

            <!-- Wire the content to the templated parent's content alignment properties -->
            <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</DataGrid.CellStyle>

字符串
进一步说明:

  • 默认情况下启用DataGrid虚拟化。同时设置DataGrid.EnableColumnVirtualizationDataGrid.EnableRowVirtualization属性。VirtualizingStackPanel.IsVirtualizing没有影响。
  • 要通过在本地设置属性来启用自定义,您应该避免在模板中(例如在CustomDataGridRowStyle中)硬编码Border.Background之类的值。而是使用{TemplateBinding}将这些属性绑定到模板化的父级,然后使用Style.Setter设置默认值。
  • 始终将实现INotfyCollectionChanged(例如,ObservableCollection)的集合设置为任何ItemsControl.ItemsSource,以提高性能(在内存管理方面)。
  • DataGridRow中DataGridCellsPresenter和DataGridDetailsPresenter元素上绑定的嵌套属性路径也无法解析。您已经使用{TemplateBinding}绑定到DataGridRow(模板化父对象)。

因此正确的属性路径是:

<!--<DataGridCellsPresenter ItemsPanel="{TemplateBinding ItemsControl.ItemsPanel}" />-->
<DataGridCellsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />

<!--<DataGridDetailsPresenter Visibility="{TemplateBinding DataGridRow.DetailsVisibility}" />-->
<DataGridDetailsPresenter Visibility="{TemplateBinding DetailsVisibility}" />

相关问题