gpt4 book ai didi

wpf - 捕捉 SurfaceListBox

转载 作者:行者123 更新时间:2023-12-04 22:06:19 29 4
gpt4 key购买 nike

我想创建一个滚动的表面列表框,它会在拖动完成后自动捕捉到一个位置,以便屏幕上的中心项目在视口(viewport)中居中。

我已经得到了中心项,但现在像往常一样,WPF 处理大小、屏幕位置和偏移量的方式让我感到困惑。

目前我选择订阅 SurfaceScrollViewer 的 ManipulationCompleted 事件,因为它似乎在我完成滚动手势后一直触发(而 ScrollChanged 事件往往会提前触发)。

void ManipCompleted(object sender, ManipulationCompletedEventArgs e)
{
FocusTaker.Focus(); //reset focus to a dummy element
List<FrameworkElement> visibleElements = new List<FrameworkElement>();
for (int i = 0; i < List.Items.Count; i++)
{
SurfaceListBoxItem item = List.ItemContainerGenerator.ContainerFromIndex(i) as SurfaceListBoxItem;
if (ViewportHelper.IsInViewport(item) && (List.Items[i] as string != "Dummy"))
{
FrameworkElement el = item as FrameworkElement;
visibleElements.Add(el);
}
}

int centerItemIdx = visibleElements.Count / 2;
FrameworkElement centerItem = visibleElements[centerItemIdx];

double center = ss.ViewportWidth / 2;

//ss is the SurfaceScrollViewer
Point itemPosition = centerItem.TransformToAncestor(ss).Transform(new Point(0, 0));

double desiredOffset = ss.HorizontalOffset + (center - itemPosition.X);

ss.ScrollToHorizontalOffset(desiredOffset);

centerItem.Focus(); //this also doesn't seem to work, but whatever.
}

列表会卡住,但卡住的地方似乎有些困惑。我在屏幕中央有一条线,有时它看起来就在项目的中间,但有时它会偏向一侧,甚至在项目之间。无法完全确定,但列表的第一和第四四分位数似乎运行良好,但第二和第三逐渐向中心偏移。

只是寻求有关如何在 WPF 中使用定位的帮助。所有相对论以及基于百分比的坐标和“屏幕单位”坐标之间的差异在这一点上让我有些困惑。

最佳答案

经过大量的尝试和错误,我最终得到了这个:

void ManipCompleted(object sender, ManipulationCompletedEventArgs e)
{
FocusTaker.Focus(); //reset focus
List<FrameworkElement> visibleElements = new List<FrameworkElement>();
for (int i = 0; i < List.Items.Count; i++)
{
SurfaceListBoxItem item = List.ItemContainerGenerator.ContainerFromIndex(i) as SurfaceListBoxItem;
if (ViewportHelper.IsInViewport(item))
{
FrameworkElement el = item as FrameworkElement;
visibleElements.Add(el);
}
}

Window window = Window.GetWindow(this);

double center = ss.ViewportWidth / 2;

double closestCenterOffset = double.MaxValue;
FrameworkElement centerItem = visibleElements[0];
foreach (FrameworkElement el in visibleElements)
{
double centerOffset = Math.Abs(el.TransformToAncestor(window).Transform(new Point(0, 0)).X + (el.ActualWidth / 2) - center);
if (centerOffset < closestCenterOffset)
{
closestCenterOffset = centerOffset;
centerItem = el;
}
}

Point itemPosition = centerItem.TransformToAncestor(window).Transform(new Point(0, 0));

double desiredOffset = ss.HorizontalOffset - (center - itemPosition.X) + (centerItem.ActualWidth / 2);

ss.ScrollToHorizontalOffset(desiredOffset);

centerItem.Focus();
}

此代码块有效地确定哪个可见列表元素与列表的中心线重叠,并将该元素对齐到准确的中心位置。捕捉有点突然,所以我必须研究某种动画,但除此之外我还是很满意的!我可能会使用这里的一些动画:http://blogs.msdn.com/b/delay/archive/2009/08/04/scrolling-so-smooth-like-the-butter-on-a-muffin-how-to-animate-the-horizontal-verticaloffset-properties-of-a-scrollviewer.aspx

编辑:没多久。我扩展了 ScrollViewerOffsetMediator 以包含 Horizo​​ntalOffset,然后按照上面帖子中的建议简单地创建了动画。奇迹般有效。希望这最终能对某人有所帮助。

Edit2:这是 SnapList 的完整代码:

SnapList.xaml

SnapList.xaml.cs

请注意,当这个项目对其中的一些内容进行硬编码时,我变得非常懒惰。需要一些自由裁量权来确定您从该代码中做什么和不想要什么。尽管如此,我认为对于任何想要此功能的人来说,这应该是一个很好的起点。

代码也与我上面粘贴的有所不同;我发现当列表位于可以移动的控件中时,使用 Windows.GetWindow 会产生不好的结果。我这样做是为了让您可以为您的移动分配一个相对于的控件(建议该控件是层次结构中列表上方的控件)。我认为其他一些事情也发生了变化;我添加了许多自定义选项,包括能够为列表定义自定义焦点。

关于wpf - 捕捉 SurfaceListBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11638084/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com