WPF----自定义滚动条ScrollViewer

滚动条是项目当中经常用到的一个控件,大部分对外项目都有外观的需求,因此需要自定义,文中主要是针对一段动态的状态数据进行展示,并保证数据始终在最新一条,就是需要滚动条滚动到底部。

1,xaml中引入
cs 复制代码
 <ItemsControl Grid.Row="1" Grid.Column="0" ItemsSource="{Binding ProcessList}" >
     <ItemsControl.ItemTemplate>
         <DataTemplate>
             <!-- 绑定到数组的每个元素 -->
             <TextBlock Text="{Binding }" Foreground="#fff" Margin="4"/>
         </DataTemplate>
     </ItemsControl.ItemTemplate>
     <ItemsControl.Template>
         <ControlTemplate TargetType="ItemsControl">
             <ScrollViewer x:Name="ScrollViewer" VerticalScrollBarVisibility="Auto"  Loaded="ScrollViewer_Loaded" >
                 <ItemsPresenter/>
             </ScrollViewer>
         </ControlTemplate>
     </ItemsControl.Template>
 </ItemsControl>

也可以直接将ScrollViewer放在所用控件的最外层。

VerticalScrollBarVisibility="Auto" 设置为auto可实现超过区域高度自动展示滚动条。

2,具体样式,放到资源中
cs 复制代码
 <Style TargetType="ScrollBar">
     <Setter Property="Width" Value="8"/>
      <!--设置滚动条宽度--> 
     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="ScrollBar">
                 <Grid Background="#212222 " Width="14" SnapsToDevicePixels="true" >
                     <Grid.RowDefinitions>
                         <!--<RowDefinition Height="Auto"/>-->
                         <RowDefinition Height="*"/>
                         <!--<RowDefinition Height="Auto"/>-->
                     </Grid.RowDefinitions>
                      <!--减少按钮--> 
                     <!--<RepeatButton Grid.Row="0" Command="ScrollBar.LineUpCommand" Content="^" Width="10" Height="10"/>-->
                      <!--轨道和滑块-->
                     <Track Grid.Row="1" Name="PART_Track"  Width="14" IsDirectionReversed="True">
                         <Track.Thumb>
                             <Thumb>
                                 <Thumb.Template>
                                     <ControlTemplate>
                                         <Border CornerRadius="2">
                                             <Rectangle  Fill="#82E4E4" RadiusX="2" RadiusY="2" Width="6"/>
                                             <!--<Thumb Width="6" Background="#82E4E4" BorderThickness="0" />-->
                                         </Border>
                                         <!--<Rectangle  Fill="#82E4E4" Width="8"/>-->
                                        
                                     </ControlTemplate>
                                 </Thumb.Template>
                             </Thumb>
                         </Track.Thumb>
                         <Track.DecreaseRepeatButton>
                             <RepeatButton Command="ScrollBar.PageUpCommand" Opacity="0"/>
                         </Track.DecreaseRepeatButton>
                         <Track.IncreaseRepeatButton>
                             <RepeatButton Command="ScrollBar.PageDownCommand" Opacity="0"/>
                         </Track.IncreaseRepeatButton>
                     </Track>
                      <!--增加按钮--> 
                     <!--<RepeatButton Grid.Row="2" Command="ScrollBar.LineDownCommand" Content="v"  Width="10" Height="10"/>-->
                 </Grid>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>
    

设置样式时候注意点:

IsDirectionReversed="True" 设置为true是保证滚动滑块随着鼠标向下滑动,为false的时候正好相反。

轨道的颜色宽度设置等,直接在Grid上面设置就好。

滑块这里用了个Rectangle,可以设置填充色,圆角、宽度等

我这边不需要上下按钮我就注释掉了。

3,滚动条始终保持在底部,在xaml.cs中实现

需要监听 ProcessList 集合的变化,并在每次添加新项后滚动到 ScrollViewer 的底部。

cs 复制代码
 public partial class F0Procedure : Page
 {
     public F0ProcedureViewModel F0ProcedureViewModel {  get; set; }
     private ScrollViewer _scrollViewer;
     public F0Procedure()
     {
         InitializeComponent();
         F0ProcedureViewModel = new F0ProcedureViewModel();
         this.DataContext = F0ProcedureViewModel;
         ((INotifyCollectionChanged)F0ProcedureViewModel.ProcessList).CollectionChanged += F0Procedure_CollectionChanged;
     }

     private void F0Procedure_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
     {
         if (e.Action == NotifyCollectionChangedAction.Add && _scrollViewer != null)
         {
             Application.Current.Dispatcher.Invoke(() =>
             {
                 Console.WriteLine(ScrollViewer.ExtentHeightProperty);
                 _scrollViewer.ScrollToVerticalOffset(_scrollViewer.ExtentHeight);
             });
         }
     }
     private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
     {
         _scrollViewer = sender as ScrollViewer;
     }
 }

我这的ProcessList是委托回调更新的,

cs 复制代码
[ObservableProperty]
private int _progressValue;


public void  UpdateExecutionProgress(string process)
{
    Application.Current.Dispatcher.BeginInvoke(new Action(() => ProcessList.Add(process)));
}

可以用 DispatcherTimer模拟,博客里也有讲过,这边都是引用的CommunityToolKit MVVM库。

4,最终结果

用到哪,学到哪,今天又是满满收获的一天。

相关推荐
界面开发小八哥1 小时前
DevExpress WPF中文教程:Grid - 如何显示摘要(设计时)?
ui·c#·wpf·界面控件·devexpress
jackfb201211 小时前
命令可以不通过数据绑定进行配置
wpf
网虫132516 小时前
WPF----进度条ProgressBar(渐变色)
wpf
小海聊工控上位机16 小时前
WPF对象样式
c#·wpf
FairyTailQ16 小时前
贰[2],WPF+HandyControl开发异常记录
开发语言·javascript·wpf
专注VB编程开发20年1 天前
基于C#在WPF中使用斑马打印机进行打印
hadoop·c#·wpf·斑马打印机·zpl打印机
云草桑1 天前
WPF UI 3D 基本概念 点线三角面 相机对象 材质对象与贴图 3D地球 光源 变形处理 动作交互 辅助交互插件 系列三
ui·3d·wpf
云草桑1 天前
WPF UI 3D 多轴 机械臂 stl 模型UI交互
ui·机器人·stl·wpf
界面开发小八哥1 天前
界面组件DevExpress WPF v24.1 - 增强的可访问性 & UI自动化
ui·wpf·界面开发·界面控件·devexpress
小海聊工控上位机2 天前
WPF对象资源
c#·wpf