• WPF中的DataGrid控件如何实现固定右侧栏效果?
  • 发布于 1个月前
  • 57 热度
    0 评论
先上效果图:

其中,Field3和Field4为右冻结列。
讲一下大致思路:

1.在DataGrid右边再放一个DataGrid,用来显示右冻结的列,把冻结的列从左边的DataGrid移除。

2.然后左边的DataGrid右侧的滚动条隐藏,横向滚动条显示,右边的DataDataGrid右侧的滚动条显示,横向滚动条显示,代码如下:

<Style x:Key="AIStudio.Styles.DataGridRightFrozen" TargetType="{x:Type controls:DataGridRightFrozen}" BasedOn="{StaticResource AIStudio.Styles.DataGrid}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:DataGridRightFrozen}">
                <Border BorderBrush="{TemplateBinding BorderBrush}"
                     BorderThickness="{TemplateBinding BorderThickness}"
                     Background="{TemplateBinding Background}"
                     Padding="{TemplateBinding Padding}"
                     SnapsToDevicePixels="True">
                 <Grid>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="*"/>
                         <ColumnDefinition Width="Auto"/>
                     </Grid.ColumnDefinitions>
                     <ScrollViewer x:Name="PART_ScrollViewer"
                            Focusable="false">
                            ...
                     </ScrollViewer>
                    <controls:DataGridScrollView x:Name="PART_Right"  Grid.Column="1" Visibility="Collapsed"
                                   ItemsSource="{TemplateBinding ItemsSource}" 
                                   AutoGenerateColumns="{TemplateBinding AutoGenerateColumns}"
                                   CanUserSortColumns="False"
                                   CanUserAddRows="False" 
                                   IsReadOnly="True" 
                                   Style="{StaticResource AIStudio.Styles.DataGrid}" 
                                   ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                                   ScrollViewer.VerticalScrollBarVisibility="{Binding ElementName=PART_ScrollViewer,Path=ComputedVerticalScrollBarVisibility}"/>
                     </Grid>
                   </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsGrouping"
              Value="true">
            <Setter Property="ScrollViewer.CanContentScroll"
                 Value="false" />
        </Trigger>
    </Style.Triggers>
</Style>
3.然后是两个DataGrid的ScrollViewer的同步滚动和选中项互相同步的问题,在CS中实现,代码如下:
 public override void OnApplyTemplate()
 {
     base.OnApplyTemplate();
     if (_scrollViewer != null)
     {
         _scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
     }
     if (_rightScrollViewer != null)
     {
         _rightScrollViewer.ScrollChanged -= _rightScrollViewer_ScrollChanged;
     }
     if (_rightDataGrid != null)
     {
         _rightDataGrid.ScrollViewerChanged -= ScrollViewerChanged;
         _rightDataGrid.SelectionChanged -= _rightDataGrid_SelectionChanged;
     }

     _scrollViewer = GetTemplateChild(PART_ScrollViewer) as ScrollViewer;
     if (_scrollViewer != null)
     {
         _scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
     }

     _rightDataGrid = GetTemplateChild(PART_Right) as DataGridScrollView;
     if (_rightDataGrid != null)
     {
         _rightDataGrid.ScrollViewerChanged += ScrollViewerChanged;
         _rightDataGrid.SelectionChanged += _rightDataGrid_SelectionChanged;
     }
     this.SelectionChanged += DataGridRightFrozen_SelectionChanged;
 }

 private void ScrollViewerChanged(ScrollViewer viewer)
 {
     _rightScrollViewer = viewer;
     _rightScrollViewer.ScrollChanged += _rightScrollViewer_ScrollChanged;
 }

 private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
 {
     if (_rightScrollViewer != null)
     {
         _rightScrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset);
     }
 }

 private void _rightScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
 {
     if (_scrollViewer != null)
     {
         _scrollViewer.ScrollToVerticalOffset(_rightScrollViewer.VerticalOffset);
     }
 }

 private void _rightDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
     this.SetCurrentValue(SelectedItemProperty, _rightDataGrid.SelectedItem);
 }

 private void DataGridRightFrozen_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
     _rightDataGrid.SetCurrentValue(SelectedItemProperty, SelectedItem);
 }
大致就是这样!

用户评论