XAML WPF Datagrid Expander的图标在上下滚动时发生变化

wsxa1bj1  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(108)

我正在开发一个WPF应用程序,其中我有一个带有自定义扩展器的数据网格。我遇到的问题是,当用户点击+按钮时,它会变成-,内容会显示出来,但是当我向下滚动,然后向上滚动时,图标会变回+,但内容保持不变。我知道这是因为数据网格的虚拟化。我可以将EnableRowVirtualization="False"添加到DataGrid属性中,但它会降低性能,以至于用户肯定会注意到它(因为列表可能包含数千行)。有办法解决这个问题吗?
下面是我的代码:

<UserControl
    x:Class="ProjectName.View.HomePage.OutstandingPatientDataGrid">

    <UserControl.Resources>
       // Other styles
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridRow}">
                        <Border>
                            <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 ItemsPanel}"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                <DataGridDetailsPresenter
                                    Grid.Row="1"
                                    Grid.Column="1"
                                    SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                    Visibility="{TemplateBinding DetailsVisibility}" />
                                <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>

        <Style TargetType="{x:Type DataGrid}">            
            <Setter Property="EnableRowVirtualization" Value="True" />
            <Setter Property="EnableColumnVirtualization" Value="True" />
            <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
            <Setter Property="VirtualizingPanel.VirtualizationMode" Value="Standard" />
            <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
        </Style>

        <ControlTemplate x:Key="SimpleExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
            <Border
                x:Name="ExpanderButtonBorder"
                >
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Rectangle Grid.ColumnSpan="2" Fill="Transparent" />
                    <Ellipse
                        Name="Circle"
                        Grid.Column="0"
                        Width="34"
                        Height="20"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Stroke="Transparent" />
                    <Path
                        x:Name="Sign"
                        Grid.Column="0"
                        Width="10"
                        Height="10"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Data="M 0,5 H 10 M 5,0 V 10 Z"
                        RenderTransformOrigin="0.5,0.5"
                        Stroke="#ADB7C9"
                        StrokeThickness="2">
                        <Path.RenderTransform>
                            <RotateTransform Angle="0" />
                        </Path.RenderTransform>
                    </Path>
                    <ContentPresenter
                        x:Name="HeaderContent"
                        Grid.Column="1"
                        Margin="4,0,0,0"
                        ContentSource="Content" />
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <!--  Change the sign to minus when toggled  -->
                <Trigger Property="IsChecked" Value="True">
                    <Setter TargetName="Sign" Property="Data" Value="M 0,5 H 10 Z" />
                </Trigger>

                <!--  MouseOver, Pressed behaviours  -->
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter TargetName="Sign" Property="Stroke" Value="{StaticResource primary-clr}" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

        <!--  Simple Expander Template  -->
        <ControlTemplate x:Key="SimpleExpanderTemp" TargetType="{x:Type Expander}">
            <DockPanel>
                <ToggleButton
                    x:Name="ExpanderButton"
                    Padding="1.5,0"
                    Content="{TemplateBinding Header}"
                    DockPanel.Dock="Top"
                    IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                    OverridesDefaultStyle="True"
                    Template="{StaticResource SimpleExpanderButtonTemp}" />
                <ContentPresenter
                    x:Name="ExpanderContent"
                    DockPanel.Dock="Bottom"
                    Visibility="Collapsed" />
            </DockPanel>
            <ControlTemplate.Triggers>
                <Trigger Property="IsExpanded" Value="True">
                    <Setter TargetName="ExpanderContent" Property="Visibility" Value="Visible" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </UserControl.Resources>

    <Grid>
        <DataGrid x:Name="outstandingPatientDataGrid" ItemsSource="{Binding}"  >
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Expander
                                Collapsed="Expander_Collapsed"
                                Expanded="Expander_Expanded"
                                Template="{StaticResource SimpleExpanderTemp}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Width="410" CanUserResize="False">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DockPanel>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Grid.Column="0">
                                        <TextBlock.Text>
                                            <MultiBinding StringFormat="{}{0} {1}">
                                                <Binding Path="FirstName" />
                                                <Binding Path="LastName" />
                                            </MultiBinding>
                                        </TextBlock.Text>
                                    </TextBlock>
                                    <TextBlock Grid.Column="1" Text="{Binding Total, StringFormat={}{0:C}}" />
                                </Grid>
                            </DockPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>

            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    // ROW STYLES
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>        
    </Grid>
</UserControl>

它看起来是这样的:塌陷:

扩展的:

代码隐藏:

using ProjectName.Classes;
using System.Windows;
using System.Windows.Controls;

namespace ProjectName.View.HomePage
{
    public partial class OutstandingPatientDataGrid : UserControl
    {
        public OutstandingPatientDataGrid()
        {
            InitializeComponent();
        }

        private void Expander_Expanded(object sender, RoutedEventArgs e)
        {
            DataGridRow row = TreeHelpers.FindParent<DataGridRow>(sender as Expander);
            row.DetailsVisibility = Visibility.Visible;
        }

        private void Expander_Collapsed(object sender, RoutedEventArgs e)
        {
            DataGridRow row = TreeHelpers.FindParent<DataGridRow>(sender as Expander);
            row.DetailsVisibility = Visibility.Collapsed;
        }
    }
}
thtygnil

thtygnil1#

关于解决方案:
您有两个事件处理程序来设置DetailsVisibility,它涵盖了用户切换扩展器切换按钮的用例。但另一种方式并不存在:当设置了DetailsVisibility(由虚拟化系统设置)时,togglebutton. Islogy未设置。
因此,我不使用eventhandlers,而是直接将IsExpanded绑定到行的DetailsVisibility:

<Expander
    IsExpanded="{Binding DetailsVisibility, RelativeSource={RelativeSource 
      AncestorType=DataGridRow}, Converter={StaticResource 
      VisibilityToBooleanConverter}, Mode=TwoWay, 
      UpdateSourceTrigger=PropertyChanged}"
    Template="{StaticResource SimpleExpanderTemp}" />

转换器应添加到UserControl的资源中:

<YourNamespace:VisibilityToBooleanConverter x:Key="VisibilityToBooleanConverter"/>

转换器的代码为:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace YourNamespace
{
    public class VisibilityToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Visibility visibility = (Visibility)value;
            return visibility == Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool booleanValue = (bool)value;
            return booleanValue ? Visibility.Visible : Visibility.Collapsed;
        }
    }
}

但除此之外,奇怪的是,你使用扩展器,因为你不使用它的标题和内容。你所需要的只是一个ToggleButton,所以我会用一个简单的ToggleButton替换Expander,并像上面那样绑定它的Islam属性。

相关问题