10

我有一个奇怪的行为VirtualizingStackPanel。我有一个包含TextBlockwith的项目列表TextWrap="Wrap"。这是代码:

<ListBox x:Name="messagesList" ItemsSource="{Binding Messages}" >
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <toolkit:ContextMenuService.ContextMenu>
                    <toolkit:ContextMenu>
                    ...
                    </toolkit:ContextMenu>
                </toolkit:ContextMenuService.ContextMenu>
                <CheckBox Style="{Binding Own, Converter={StaticResource MsgTypeToStyle}}"
                          Tag="{Binding TimeString}"
                          IsEnabled="True">
                    <TextBlock Text="{Binding Content}" TextWrapping="Wrap"/>
                </CheckBox>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

它工作得很好,但是如果我尝试非常快地滚动(在模拟器上使用鼠标,而不是使用鼠标)滚动会有一些滞后,HorizontallOffset有时可能计算错误,并且在底部以非常奇怪的结果结束(见图,右图演示正常行为)。

滚动错误

经过研究,我发现了这个问题VirtualizingStackPanelTextBlock.TextWrap="Wrap"如果我从这对夫妇中删除一个元素,所有的工作都正常。

但是我需要虚拟化,因为项目数量很大,并且TextWrap要正确显示文本。

所以我想自己实现虚拟化面板,请你指导我,如何做到这一点,或者如何解决当前的问题?

UPD:问题:
前两个图像ListBox已经(!)滚动到底部(不能再向下滚动),但元素放置不正确,正确放置显示在右侧图像上。仅当您滚动非常快时才会发生这种情况。

UPD2:感谢米兰阿加瓦尔。他在这里为我的问题提供了一个很好的案例。看来这确实是ListBox. 提供的解决方法不适合我的场景,因为我需要与ListBoxitem 内部的控件进行交互。现在我正在尝试捕获ManipulationCompleted事件并检查它是否是Inertial,如果是,则意味着滚动,我将焦点设置为页面:

    void messagesList_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
    {
        if (e.IsInertial)
            this.Focus();
    }

PS感谢祝你好运;)

4

4 回答 4

9

为了克服滚动时出现的黑色,您需要虚拟化滚动控件。为此,您应该继承IList并创建Collection自己的类似ObservableCollection内容,您必须根据缓存要求覆盖默认索引器,同时为您的项目维护缓存。我觉得这可能是您正在寻找的:http: //blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx

该页面上有一个示例项目。试试看。

我也觉得你正面临这个问题http://blog.rsuter.com/?p=258。我想这将使用虚拟化本身来解决。希望能帮助到你

于 2012-08-17T13:06:41.317 回答
1

第二屏有什么问题?你的意思是最后一条消息后有很大的空白空间?最后一条消息没有放在页面底部?我做对了吗?

实际上我并没有尝试重现您的代码和错误,但我的观点是,既然您在应用程序中使用了 3rd 方库(Silverlight Toolkit),为什么不也使用Coding4Fun 工具呢?

我写了这个虚拟类:

public class Message
{
    public string Time { get; private set; }
    public string Content { get; private set; }

    public Message(string time, string content)
    {
        Time = time;
        Content = content;
    }
}

然后我把这个虚拟代码放在主页构造函数中:

var _messages = new ObservableCollection<Message>();

for (int i = 0; i < 50; i++)
{
    _messages.Add(new Message("12:40", "Teh very long string which should be wrapped. Pavel Durov gives WP7 Contest winners less money than he did for Android/iOS winners. FFFUUUUUUUUUUUUUU "));
}

this.ListBox.ItemsSource = _messages;

在 xaml 中,我放置了一个带有工具包聊天气泡控制的列表框:

<ListBox x:Name="ListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <c4fToolkit:ChatBubble>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="0"
                               Text="{Binding Content}"
                               TextWrapping="Wrap"/>
                    <TextBlock Grid.Row="1"
                               Text="{Binding Time}"
                               HorizontalAlignment="Right"/>
                </Grid>
            </c4fToolkit:ChatBubble>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我运行它并没有看到任何奇怪的行为,也许有点滞后。结果是:

dat图片很大

希望我能帮上忙。


Удачи с конкурсом, я б сам поучаствовал, но не верю, что за 1,5 месяца удастся сделать приличный клиент。

于 2012-08-17T09:08:25.990 回答
1

第二张图有什么问题?是 BlackArea 完全出现了,还是 ScrollView 在滚动结束后没有“反弹”以填充黑色区域的内容?

了解这一点至关重要,因为......这种效果对于 WPF/WP7 来说是很自然的......顺便说一句。滚动条在过度滚动后应该“反弹”,但它似乎有一个错误,有时会忘记这样做。

我之所以问,是因为黑/白区域不仅在 WP7 上,而且在任何有带有惯性滚动的 XAMLish ScrollViewer 的地方。您会看到,当滚动速度快于平台提供新项目时,您只需滚动到预先计算的项目之外,一旦您“过度”滚动很远,缓慢进入的项目突然发现没有更多项目,因此 -回空区..

这主要发生在某些情况同时发生时:您快速滚动(耶),您的绑定很慢(过于复杂的表达式),您的模板渲染很慢(复杂的不可重用的 UI 模板),绑定不知道有多少项目有(必然IEnumerable没有IList-> 没有 .Count 信息!),或者渲染器不知道要为一个项目保留多少高度(该项目不是恒定高度,但必须计算每个项目以确定其自己的确切高度)。

如果你想纠正它,你必须首先解决这些原因,或者你必须实现自己的滚动或侵入虚拟化堆栈面板并将来自 bindingsource 的项目的馈送与滚动同步,以让滚动条更好地猜测总高度:例如,一次只显示一个小项目,监听滚动事件并从列表的头部/尾部动态添加/删除下一包项目。这将通过不允许快速滚动来解决问题:)))))

我相信限制项目高度是最简单的方法。你不能做一些聪明的事情来让这些物品实际上是恒定大小的吗?

于 2012-08-17T13:32:30.583 回答
1

我建议您创建最简单的函数来计算包装文本块的高度并绑定到它。这样,您可以在列表框中获得可变高度项目的好处,但可以继续使用虚拟化堆栈面板。

于 2012-08-21T21:49:00.580 回答