WPF,ListBox逐项滚动到基于像素的滚动 [英] WPF, ListBox item-by-item scrolling to pixel based scrolling
问题描述
当我插入listboxItem时,我正在使用以下代码修复屏幕.
I'm using below code for fix my screen when i insert listboxItem.
public partial class KeepItemsInViewListBox : ListBox
{
private ScrollViewer ScrollViewer { get; set; }
#region Overrides of FrameworkElement
/// <inheritdoc />
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (TryFindVisualChildElement(this, out ScrollViewer scrollViewer))
{
this.ScrollViewer = scrollViewer;
}
}
#endregion
#region Overrides of ListView
/// <inheritdoc />
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (this.ScrollViewer == null)
{
return;
}
double verticalOffset;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add when e.NewItems != null:
// Check if insert or add
verticalOffset = e.NewStartingIndex < this.ScrollViewer.VerticalOffset
? this.ScrollViewer.VerticalOffset + e.NewItems.Count
: this.ScrollViewer.VerticalOffset;
break;
case NotifyCollectionChangedAction.Remove when e.OldItems != null:
verticalOffset = this.ScrollViewer.VerticalOffset - e.OldItems.Count;
break;
default:
verticalOffset = this.ScrollViewer.VerticalOffset;
break;
}
this.ScrollViewer?.ScrollToVerticalOffset(verticalOffset);
}
#endregion
public bool TryFindVisualChildElement<TChild>(DependencyObject parent, out TChild childElement)
where TChild : FrameworkElement
{
childElement = null;
if (parent == null)
{
return false;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TChild resultElement)
{
childElement = resultElement;
return true;
}
if (TryFindVisualChildElement(child, out childElement))
{
return true;
}
}
return false;
}
}
该类使我的列表框滚动到逐项显示.
that class makes my listbox's scroll to item-by-item.
请参见下图.
在上层类(KeepItemsInViewListBox)之前,我的滚动条件是Pixel.但是使用该代码后,我的滚动条件发生了变化.
before upper Class(KeepItemsInViewListBox), my scrolling condition is Pixel. but after using that code my scrolling condition is changed.
因为我所有的 listboxitem 的大小都不同,我在xaml中添加了 VirtualizingPanel.ScrollUnit ="Pixel"
或 ScrollViewer.CanContentScroll ="False"
,或 ScrollViewer.CanContentScroll = false;
在.cs文件中然后我的屏幕也移动了...
because all of my listboxitem's size is diffrent,
I added VirtualizingPanel.ScrollUnit="Pixel"
or ScrollViewer.CanContentScroll = "False"
in xaml, or ScrollViewer.CanContentScroll = false;
in .cs file
then my screen is also move...
推荐答案
首先要感谢Mr.Code
First thanks to Mr.Code
我修改了Code先生的班级,但是我的Code并不完美.
I modify Mr.Code's class, but my Code is not a perfect.
public class KeepItemsInViewListBox : ListBox
{
private ScrollViewer ScrollViewer { get; set; }
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (insertCheck)
{
ScrollViewer.ScrollToVerticalOffset(ScrollViewer.VerticalOffset + e.ExtentHeightChange);
insertCheck = false;
}
}
#region Overrides of FrameworkElement
/// <inheritdoc />
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (TryFindVisualChildElement(this, out ScrollViewer scrollViewer))
{
this.ScrollViewer = scrollViewer;
ScrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
}
}
#endregion
private bool insertCheck = false;
#region Overrides of ListView
/// <inheritdoc />
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
switch (e.Action)
{
case NotifyCollectionChangedAction.Add when e.NewItems != null:
bool isInsert = this.ScrollViewer.CanContentScroll
? e.NewStartingIndex < this.ScrollViewer.VerticalOffset
: e.NewStartingIndex + 1 != this.Items.Count - 1;
if (!isInsert)
{
return;
}
insertCheck = isInsert;
break;
}
}
#endregion
public bool TryFindVisualChildElement<TChild>(DependencyObject parent, out TChild childElement)
where TChild : FrameworkElement
{
childElement = null;
if (parent == null)
{
return false;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TChild resultElement)
{
childElement = resultElement;
return true;
}
if (TryFindVisualChildElement(child, out childElement))
{
return true;
}
}
return false;
}
}
我只是重新定义了"ScrollViewer_ScrollChanged"方法,然后将verticalOffset设置为更改的偏移值.
I just redefine "ScrollViewer_ScrollChanged" method and set verticalOffset to changed offset value.
它在我的测试项目中有效.但在我的真实项目中不起作用.然后,我使用ScrollViewer的ExtentHeight值.我检查了第一个ExtentHeight并保存了它.滚动后,我比较两个ExtentHeight并将差异设置为verticalOffset.
It works in my test Project. but in my real Project doesn't work. Then i use ScrollViewer's ExtentHeight value. I checked the first ExtentHeight and it was saved. After scrolling, I compare two of ExtentHeight and set the diffrence to verticalOffset.
但是它不能很好地工作
这篇关于WPF,ListBox逐项滚动到基于像素的滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!