4

シンプルなメニュー/選択デザインツールを作成する必要があります。アイデアは、カテゴリを選択し、選択したカテゴリによってフィルタリングされる選択肢を増やすことです。最終的に、これはキオスクスタイルの環境で実行されます。

私はMVVMを使用しており、デザインは2つのItemsControl内に2つのグリッドを含むビューで構成されています。1つはカテゴリ(2行x 10列)用で、もう1つは選択肢(10 x 10)用です。私のViewModelでは、これらのItemsControlは両方ともObservableCollectionオブジェクトにバインドされており、一部の詳細(キャプション、色など)はパーツのプロパティにバインドされています。DataTemplateは、キオスクアプリでも再利用したいので、別のアセンブリのアイテムクラスにバインドされています。

「ModifiedBehaviours」クラスを使用して、グリッドオブジェクトの右クリックと左クリックを、これに似たViewModelによって取得されたコマンドにマップしました。

2つのアタッチされたビヘイビアーを1つのXAML要素にアタッチするにはどうすればよいですか?

私が読んだもの(ここではMVVMに比較的新しい)から、デザインは「クリーン」に見えます。ビューのコードビハインドには、ViewModelをウィンドウのDataContextに割り当て、ビューにx:name =タグがなく、 ViewModelはビューと直接相互作用しません。

ただし、パフォーマンスに問題があります。

ユーザーがカテゴリをクリックすると、その詳細アイテムを含む新しいObservableCollectionが作成されます。デザインモードでも空白を埋めるため、100の選択肢があり、空の選択肢には「右クリックして編集」が含まれています。

このコレクションを作成する時間はごくわずかです。1.6Ghzネットブックでは0.01秒未満です(キオスクPCは低速になるため、低速のハードウェアでテストしています)。ただし、コントロールがバインドされているコレクションが更新されると、UIの更新に約2秒かかります。これは、私が再作成している古いアプリ(非常に古いDelphiで記述されている)よりもはるかに低速です。

いろいろ試してみました。最初に、グラデーションやその他のものを削除してXAMLを単純化し、可能な限り単純にしました。最終的には1つのテキストブロックになりました。次に、コレクションを更新するときに、コレクションを個別に作成し、バインドされたコレクションに割り当てて、更新が「一度に」行われるようにします。3番目に、デザインを少し壊して、ウィンドウとグリッドの更新コードの周りにBeginInit()とEndInit()を追加しました。

これらのどれもわずかな改善をしませんでした。

以下はそうしました-それは私の質問につながります。

  1. コマンドの動作の1つをアイテムコントロールから削除しました。右クリックと左クリックの両方が必要です。これが各アイテムセル(そのうちの100個)のイベントをコマンドにバインドする必要があるという事実が問題を引き起こす可能性がありますか?

各グリッドセルの右クリックと左クリックの代替アプローチはありますか?

  1. <-これは私のマークアップで2です!アイテム(境界線、テキストブロック、およびコマンド)のXAMLを個別のアセンブリからメインウィンドウのXAMLにコピーしました。これは最大の単純な改善をもたらしましたが、その理由はわかりません。

両方が別々に違いを生み、両方が一緒になってパフォーマンスを「許容できる」ものにしますが、それでも非常に遅いです。他に見られるものはありますか?

私のコントロールはこのように見えます(別のアセンブリで)。上記のように誰かが指摘する前に、私はこれをたくさん削除し、これをただのテキストブロックに切り詰めようとしました。

<Control.Resources>
    <Style x:Key="MyBorderStyle" TargetType="Border">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsSelected}" Value="True">
                <Setter Property="BorderBrush" Value="Red"/>
                <Setter Property="BorderThickness" Value="3"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsSelected}" Value="False">
                <Setter Property="BorderBrush" Value="{Binding BackColour}"/>
                <Setter Property="BorderThickness" Value="0"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Control.Resources>
<Grid>
    <Border Margin="1" Style="{StaticResource MyBorderStyle}" CornerRadius="8">
        <CommandBehaviour:CommandBehaviorCollection.Behaviors>
            <CommandBehaviour:BehaviorBinding Event="MouseLeftButtonDown" Command="{Binding DataContext.SelectLeftCommand, 
                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" CommandParameter="{Binding ItemKey}"/>
            <CommandBehaviour:BehaviorBinding Event="MouseRightButtonDown" Command="{Binding DataContext.SelectRightCommand, 
                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" CommandParameter="{Binding ItemKey}"/>
        </CommandBehaviour:CommandBehaviorCollection.Behaviors>
        <Border.Background>
            <LinearGradientBrush StartPoint="0.7,0" EndPoint="0.7,1">
                <GradientStop Color="{Binding BackColour}" Offset="0"/>
                <GradientStop Color="#33333333" Offset="1.5"/>
            </LinearGradientBrush>
        </Border.Background>
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{Binding ForeColour}" Text="{Binding Description}"/>
    </Border>
</Grid>

これをメインウィンドウのItemsTemplateにコピーすると、パフォーマンスの向上が維持されるため、この多くをそのままにしておくことができます。

ステートメント-RantWPFの最大の問題の1つは、パフォーマンス(およびその他の)問題の多くがどこか(舞台裏のコード)の「うさぎの穴」にあり、何が起こっているのかを理解するのが非常に難しいことです。外部の、時には非常に複雑なパフォーマンスおよびプロファイリングツールがなく、それらをダウンロード、インストール、および学習する時間もありません。

本当にパンツです。

そして息をして...ステートメントの終わり-暴言

4

2 に答える 2

1

それがあなたの問題です。

「ユーザーがカテゴリをクリックすると、詳細アイテムを含む新しいObservableCollectionが作成されます」

新しいコレクションの作成にはコストがかかります。ユーザーのクリックごとに制限される新しいコレクションの作成には、非常にコストがかかります。

コレクションを一度だけ作成して、再利用することはできますか?
(それは単なる知識に基づいた賭けですが、私があなただったら私が目指すものです)

于 2012-07-16T07:47:20.340 に答える
1

コレクションを更新するときは、コレクションを個別に作成してから、バインドされたコレクションに割り当てて、更新が「一度に」行われるようにします。

更新だけの場合は、新しいアイテムを作成するのObservableCollectionではなく、アイテムを追加/削除するだけです。新しいものを割り当てるObservableCollectionと、WPFエンジンが古いUIをクリアし、UI全体を再度レンダリングすることになり、時間がかかります。

また、パフォーマンスに影響を与えるバインディングエラーも確認します。デバッグモードでVisual Studioの出力ウィンドウを確認すると、バインディングエラーの詳細が表示されます。これはRelativeSourceバインディングでよく発生し、あなたの場合にもボトルネックになる可能性があります。

于 2012-07-16T09:18:27.070 に答える