5

ListBox使用するようにスタイル設定された がRadioButtonsあり、 を変更すると、その下に表示されるSelectedItemも変更されます。アプリケーションは次のようになります。UserControlContentControl

アプリのモックアップ

<ListBox ItemsSource="{Binding AvailableViewModels}"
         SelectedItem="{Binding SelectedViewModel}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

<ContentControl Content="{Binding SelectedViewModel}" />

私の問題は、UserControlsそれぞれにカスタマイズされた Grid コントロール (Telerik のRadGridView) が含まれていることです。これには、含まれるデータの量が原因でロード時に顕著な遅延があります。

ItemsSourceグリッドのロード後にイベントでバインディングを設定してLoaded、グリッドのロード中に UI がロックされないようにしていますが、これをどのように実行しようとしても、RadioButtons はロード中の遅延を反映し、フリーズしたように見えます。 UI

読み込み中のラジオ ボタンのスクリーンショット

バインディングの設定に可能な限り低いDispatcherPriorityを使用してみましたが、違いはないようです。

XAML:

<telerik:RadGridView x:Name="MyGrid" Loaded="MyGrid_Loaded" Unloaded="MyGrid_Unloaded">
     <!--....-->
</telerik:RadGridView>

C#:

private void MyGrid_Loaded(object sender, RoutedEventArgs e)
{
    this.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,
        new Action(delegate()
    {
        BindingOperations.SetBinding(
            MyGrid,
            RadGridView.ItemsSourceProperty,
            new Binding("ViewModelProperty")
        );
    }));
}

private void MyGrid_Unloaded(object sender, RoutedEventArgs e)
{
    MyGrid.ItemsSource = null;
}

UserControlそれぞれが最初にロードされるときは、RadioButton選択がすぐに変更され、数秒後にグリッドがロードされて問題なくロードされることに注意してください。から切り替えてUserControl再び戻るだけでRadioButtons、選択中に が一時停止します。

ビューを切り替えたときに UI がフリーズしたように見える原因、またはそれを解決する方法について何か考えがある人はいますか?

編集

RadioButtons問題の小さな再現を作成しましたが、ListBoxアイテムに使用した場合にのみ発生することがわかりました. レギュラーを使用してListBoxも、選択動作に同じ遅延は発生しません。

XAML:

<Window.Resources>

    <!-- Need two separate DataTemplates -->
    <DataTemplate DataType="{x:Type local:Test}">
        <StackPanel>
            <TextBlock Text="Test" />
            <TextBlock Margin="10" Loaded="TextBlock_Loaded" />
            <TextBlock Text="Test" />
        </StackPanel>
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:Test2}">
        <StackPanel>
            <TextBlock Text="Abc" />
            <TextBlock  Margin="10" Loaded="TextBlock_Loaded" />
            <TextBlock Text="Abc" />
        </StackPanel>
    </DataTemplate>

    <Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="{x:Type ListBoxItem}" >
                    <Setter Property="Margin" Value="2, 2, 12, 2" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Border Background="Transparent">
                                    <RadioButton
                                            Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                            ContentTemplate="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=ItemTemplate}"
                                            IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

<StackPanel>
    <ListBox x:Name="TestListBox"
             ItemsSource="{Binding Test}"
             Style="{StaticResource RadioButtonListBoxStyle}">

        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="Option" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ContentControl Content="{Binding ElementName=TestListBox, Path=SelectedItem}" />
</StackPanel>

C#:

private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
    this.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle,
        new Action(delegate()
        {
            System.Threading.Thread.Sleep(1000);
            ((TextBlock)sender).Text = "Delay Loaded Test";
        }));
}

Testは、とオブジェクトObservableCollection<ITest>の両方を含む単純なです。既存の を再利用する代わりに新しいオブジェクトが描画されるため、遅延は 2 つの異なるオブジェクトを切り替えるときにのみ発生します。TestTest2DataTemplateDataTemplate

4

1 に答える 1

4

ディスパッチャと低い優先度を使用する場合の問題は、コードがいつ実行されるかについて実際の保証がないことです。UI の更新後に実行速度の遅いコードが確実に実行されるようにする必要があります。これを行うためのかなりハックな方法を考えることができます...

DispatcherTimer timer = new DispatcherTimer();
timer.Interval = Timespan.FromMilliseconds(100);
timer.Tick += (s, e2) =>
{
  // update your binding
  BindingOperations.SetBinding(
        MyGrid,
        RadGridView.ItemsSourceProperty,
        new Binding("ViewModelProperty")
    );

  timer.Stop();
};
timer.Start();

上記は、100 ミリ秒後に実行される単一の「ティック」タイマーを作成します。

于 2012-08-21T12:54:06.930 に答える