Ric*_*ter 9 silverlight xaml windows-phone-7 windows-phone-7.1
我ListBox在Windows Phone 7 Silverlight中扩展了一个类的问题.想法是拥有一个完整的ScrollViewer(黑色,例如填充整个手机屏幕),并且ItemsPresenter(红色)有一个边距(绿色).这用于在整个列表周围有一个边距,但滚动条从右上边缘开始,到深暗矩形的右下边缘结束:

问题是,ScrollViewer无法滚动到最后,它会从列表中的最后一个元素中删除50个像素.如果我使用StackPanel而不是VirtualizingStackPanel边距是正确的但是列表不再虚拟化.
感谢任何想法,我已经尝试了很多,但没有任何工作.这是一个控制错误吗?
解决方案:使用MyToolkit库中控件的InnerMargin属性!ExtendedListBox
C#:
public class MyListBox : ListBox
{
public MyListBox()
{
DefaultStyleKey = typeof(MyListBox);
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
更新1
我创建了一个简单的示例应用程序:滚动条最后无法滚动...如果您在App.xaml中更改为VirtualizingStackPanelto StackPanel并且它按预期工作但没有虚拟化
更新2 添加了一些示例图片.滚动条呈蓝色显示其位置.
预期结果(使用StackPanel而不是VirtualizingStackPanel):
Correct_01:顶部的滚动条
Correct_01:中间的滚动条

Correct_01:底部的滚动条

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

唯一的解决方案是在列表的末尾添加一个虚拟元素来补偿边距.我将尝试在控制逻辑中动态添加此虚拟元素...将一些逻辑添加到绑定中ObservableCollection或视图模型中没有选项.
更新:我将我的最终解决方案添加为单独的答案.签出ExtendedListBox类.
我当前的解决方案:始终更改列表最后一个元素的边距......
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个“hack”来动态更改最后一个列表项的边距(不需要向绑定列表添加某些内容)我开发了这个最终控件:
(列表框有一个新的事件 for PrepareContainerForItem,一个属性和事件 for IsScrolling(还有一个扩展的LowProfileImageLoaderwithIsSuspended属性,可以在事件中设置,以提高滚动平滑度...)以及所描述问题的IsScrolling新属性...InnerMargin
更新:查看我的 MyToolkit 库的ExtendedListBox类,它提供了此处描述的解决方案...
| 归档时间: |
|
| 查看次数: |
1965 次 |
| 最近记录: |