XML
<ListBox
Name="MessagesItemsControl"
Background="Transparent"
BorderThickness="0"
ItemsSource="{Binding Messages}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding CurrentMessage}">
<ListBox.Styles>
<Style Selector="ListBoxItem:selected /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="ListBoxItem:not(:focus) /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="ListBoxItem:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
</ListBox.Styles>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="vm:ChatMessageViewModel">
<chat:ChatMessageView Margin="2,0,6,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
操作滚动条
cs
//MessagesItemsControl.AttachedToVisualTree += (_, __) =>
//{
// Avalonia.Threading.Dispatcher.UIThread.Post(() =>
// {
// var chatScrollViewer = MessagesItemsControl.FindDescendantOfType<ScrollViewer>();
// HookScrollEvents(chatScrollViewer);
// });
//};
//private void HookScrollEvents(ScrollViewer? ChatScrollViewer)
//{
// if (ChatScrollViewer == null)
// return;
// // ListBox SelectedItem change
// MessagesItemsControl
// .GetObservable(ListBox.SelectedItemProperty)
// .Subscribe(new AnonymousObserver<object?>(_ =>
// {
// _scrollToEnd = true;
// }));
// // ScrollViewer.ExtentProperty
// ChatScrollViewer
// .GetObservable(ScrollViewer.ExtentProperty)
// .Subscribe(new AnonymousObserver<Size>(_ =>
// {
// double bottomThreshold = 50;
// double distanceToBottom = ChatScrollViewer.Extent.Height -
// (ChatScrollViewer.Offset.Y + ChatScrollViewer.Viewport.Height);
// bool isNearBottom = ChatScrollViewer.Extent.Height <= ChatScrollViewer.Viewport.Height
// || distanceToBottom <= bottomThreshold;
// if (isNearBottom || _scrollToEnd)
// {
// ChatScrollViewer.ScrollToEnd();
// _scrollToEnd = false;
// }
// }));
// // windows change(Bounds)
// this.GetObservable(BoundsProperty)
// .Subscribe(new AnonymousObserver<Rect>(_ =>
// {
// ChatScrollViewer.ScrollToEnd();
// }));
//}