gpt4 book ai didi

silverlight - 虚拟化 ListBox 的 ItemsControl 的边距无法正常工作

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

我对扩展 ListBox 的类有疑问在 Windows Phone 7 Silverlight 中。这个想法是有一个完整的ScrollViewer (黑色,例如填满整个手机屏幕)并且 ItemsPresenter (红色)有边距(绿色)。这用于在整个列表周围留有边距,但滚动条从右上边缘开始,到深色矩形的右下边缘结束:

enter image description here

问题是,ScrollViewer无法滚动到最后,它会从列表中的最后一个元素中删除 50 个像素。如果我使用 StackPanel而不是 VirtualizingStackPanel边距是正确的,但列表不再是虚拟化的。

感谢您的任何想法,我已经尝试了很多,但没有任何工作。这是控制错误吗?

解决方案:使用 InnerMargin ExtendedListBox 的属性(property)来自 MyToolkit 的控制图书馆!

C#:

public class MyListBox : ListBox
{
public MyListBox()
{
DefaultStyleKey = typeof(MyListBox);
}
}

XAML(例如 App.xaml):
<Application 
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">

<Application.Resources>
<ResourceDictionary>
<Style TargetType="local:MyListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter Margin="30,50,30,50" x:Name="itemsPresenter" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>

...
</Application>

更新 1

我创建了一个简单的示例应用程序:滚动条最终无法滚动...如果您更改 VirtualizingStackPanelStackPanel在 App.xaml 中,它按预期工作,但没有虚拟化

SampleApp.zip

更新 2
添加了一些示例图片。滚动条是蓝色的以显示它们的位置。

预期结果(使用 StackPanel 而不是 VirtualizingStackPanel ):

Correct_01:顶部的滚动条

enter image description here

Correct_01:中间的滚动条

enter image description here

Correct_01:底部的滚动条

enter image description here

错误示例:

Wrong_01:边距始终可见(例如:滚动位置中间)

enter image description here

唯一的解决方案是在列表末尾添加一个虚拟元素以补偿边距。我将尝试在控制逻辑中动态添加这个虚拟元素...在绑定(bind) ObservableCollection 中添加一些逻辑或者 View 模型是没有选择的。

更新:我将最终解决方案添加为单独的答案。
查看 ExtendedListBox类(class)。

最佳答案

我当前的解决方案:始终更改列表最后一个元素的边距...

public Thickness InnerMargin
{
get { return (Thickness)GetValue(InnerMarginProperty); }
set { SetValue(InnerMarginProperty, value); }
}

public static readonly DependencyProperty InnerMarginProperty =
DependencyProperty.Register("InnerMargin", typeof(Thickness),
typeof(ExtendedListBox), new PropertyMetadata(new Thickness(), InnerMarginChanged));

private static void InnerMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var box = (ExtendedListBox)d;
if (box.lastElement != null)
box.UpdateLastItemMargin();
box.UpdateInnerMargin();
}

private void UpdateInnerMargin()
{
if (scrollViewer != null)
{
var itemsPresenter = (ItemsPresenter)scrollViewer.Content;
if (itemsPresenter != null)
itemsPresenter.Margin = InnerMargin;
}
}

private void UpdateLastItemMargin()
{
lastElement.Margin = new Thickness(lastElementMargin.Left, lastElementMargin.Top, lastElementMargin.Right,
lastElementMargin.Bottom + InnerMargin.Top + InnerMargin.Bottom);
}

private FrameworkElement lastElement = null;
private Thickness lastElementMargin;
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
OnPrepareContainerForItem(new PrepareContainerForItemEventArgs(element, item));

if ((InnerMargin.Top > 0.0 || InnerMargin.Bottom > 0.0))
{
if (Items.IndexOf(item) == Items.Count - 1) // is last element of list
{
if (lastElement != element) // margin not already set
{
if (lastElement != null)
lastElement.Margin = lastElementMargin;
lastElement = (FrameworkElement)element;
lastElementMargin = lastElement.Margin;
UpdateLastItemMargin();
}
}
else if (lastElement == element) // if last element is recycled it appears inside the list => reset margin
{
lastElement.Margin = lastElementMargin;
lastElement = null;
}
}
}

使用此“hack”动态更改最后一个列表项的边距(无需向绑定(bind)列表添加某些内容)我开发了这个最终控件:
  • https://xp-dev.com/svn/mytoolkit/Shared/Controls/ExtendedListBox.cs

  • (列表框有一个新的 PrepareContainerForItem 事件,一个属性和 IsScrolling 的事件(还有一个扩展的 LowProfileImageLoaderIsSuspended 属性,可以在 IsScrolling 事件中设置以提高滚动平滑度。 ..) 和新属性 InnerMargin 用于描述的问题...
  • https://xp-dev.com/svn/mytoolkit/Shared/Media/ImageHelper.cs

  • 更新:查看 ExtendedListBox我的 MyToolkit 库的类,它提供了此处描述的解决方案...

    关于silverlight - 虚拟化 ListBox 的 ItemsControl 的边距无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8008929/

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