滚动条是项目当中经常用到的一个控件,大部分对外项目都有外观的需求,因此需要自定义,文中主要是针对一段动态的状态数据进行展示,并保证数据始终在最新一条,就是需要滚动条滚动到底部。
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,最终结果
用到哪,学到哪,今天又是满满收获的一天。