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間違った計算をし、下部で非常に奇妙な結果になります(画像、右の画像を参照)正常な動作を示します)。

スクロールバグ

調査の後、私はその問題を組み合わせて理解し、このカップルから 1 つの要素を削除するVirtualizingStackPanelTextBlock.TextWrap="Wrap"、すべて正しく動作します。

TextWrapしかし、アイテム数が多く、正しいテキスト表示のために仮想化が必要です。

そこで、Virtualizing Panel を独自に実装することを考えています。これを行う方法、または現在の問題を修正する方法を教えていただけますか?

UPD: 問題:
最初の 2 つの画像ListBoxは既に (!) 一番下までスクロールされていますが (これ以上下にスクロールすることはできません)、要素が正しく配置されておらず、正しい配置が右の画像に示されています。これは、非常に速くスクロールする場合にのみ発生します。

UPD2: Milan Aggarwal に感謝します。彼はここで私の問題の良い例を提供してくれました。それは本当にバグのようListBoxです。ListBoxアイテム内のコントロールを操作する必要があるため、提供された回避策は私のシナリオには適合しません。今、私はManipulationCompletedイベントをキャッチして、それが であるかどうかを確認しようとしていInertialます。そうであれば、それはスクロールを意味し、ページにフォーカスを設定します:

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

PS 幸運を祈ります;)

4

4 に答える 4

9

スクロール時の黒の発生を克服するには、スクロール コントロールを仮想化する必要があります。そのためには、キャッシュ要件に応じてデフォルトのインデクサーをオーバーライドし、同時にアイテムのキャッシュを維持する必要があるのと同様に、独自のものを継承IListして作成する必要があります。私はこれがあなたが探しているものかもしれないと感じています:CollectionObservableCollection

そのページにサンプルプロジェクトがあります。それを試してみてください。

また、この問題http://blog.rsuter.com/?p=258に直面していると思います。これは仮想化そのもので解決できると思います。それが役に立てば幸い

于 2012-08-17T13:06:41.317 に答える
1

2番目の画面の問題は何ですか?最後のメッセージの後に大きな空きスペースがあるということですか?最後のメッセージがページの下部に表示されていませんか?私はこれを正しく理解していますか?

実際、私はコードとバグを再現しようとはしませんでしたが、私のポイントは、アプリでサードパーティのライブラリ(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>

私はそれを実行しましたが、奇妙な動作は見られませんでした。おそらく少し遅れています。結果があります:

datpicは巨大です

私が助けてくれたことを願っています。


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

于 2012-08-17T09:08:25.990 に答える
1

2番目の画像の問題は何ですか?BlackArea がまったく表示されたということですか、それとも、スクロールが終了して黒い領域をコンテンツで埋めるために ScrollView が「跳ね返って」いないということですか?

... この効果は WPF/WP7 にとって単純に自然なので、これを知ることは非常に重要です.. ところで。スクローラーはオーバースクロール後に「跳ね返る」はずですが、バグがあり、時々それを忘れているようです。

黒/白の領域はWP7だけでなく、慣性スクロールを備えたXAMLish ScrollViewerがある場所によくあるため、私が尋ねています。ご覧のとおり、プラットフォームが新しいアイテムを提供できるよりも速くスクロールすると、事前に計算されたアイテムの外にスクロールするだけで、非常に遠くまで「オーバー」スクロールすると、ゆっくりと入ってくるアイテムが突然、それ以上アイテムがないことに気付きます。後ろの空き地..

これは主に、いくつかの条件が同時に発生した場合に発生します: スクロールが速い (イェーイ)、バインディングが遅い (過度に複雑な式)、テンプレートのレンダリングが遅い (複雑で再利用できない UI テンプレート)、バインディングがアイテムの数を認識していないあります (not to IEnumerablenot IList-> no .Count information!)、またはレンダラーがアイテムに確保する高さを知りません (アイテムは一定の高さではありませんが、アイテムごとに正確な高さを決定するために計算する必要があります) )。

それを修正したい場合は、最初にこれらの原因と戦うか、独自のスクロールを実装するか、仮想化スタック パネルにハックし、バインディングソースからのアイテムのフィードをスクロールと同期させて、スクローラーが全体の高さをより適切に推測できるようにする必要があります。たとえば、 、一度に小さなアイテムのみを表示し、スクロールイベントをリッスンし、リストの先頭/末尾から次のアイテムのパックを動的に追加/削除します..これにより、高速スクロールを許可しないことで問題が解決します:)))))

アイテムの高さを制限するのが最も簡単な方法だと思います。アイテムを実際に一定のサイズにするために何か賢いことはできませんか?

于 2012-08-17T13:32:30.583 に答える
1

ラップされたテキストブロックの高さを計算し、それにバインドする最も単純な関数を作成することをお勧めします。このようにして、リストボックス内の可変高さのアイテムの利点を得ることができますが、仮想化スタック パネルを引き続き使用することができます。

于 2012-08-21T21:49:00.580 に答える