我的ListBox
风格设计为使用RadioButtons
,更改SelectedItem
也会更改其下方UserControl
中显示的ContentControl
。该应用程序如下所示:
<ListBox ItemsSource="{Binding AvailableViewModels}"
SelectedItem="{Binding SelectedViewModel}"
Style="{StaticResource RadioButtonListBoxStyle}" />
<ContentControl Content="{Binding SelectedViewModel}" />
我的问题是UserControls
每个都包含一个自定义网格控件(Telerik的RadGridView
),由于其包含的数据量,它在加载时会有明显的延迟。
我在Grid加载后在ItemsSource
事件中设置Loaded
绑定,以防止UI在Grid加载时锁定,但无论我如何尝试运行它,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>
,其中包含Test
和Test2
个对象。延迟仅在两个不同对象之间切换时发生,因为绘制了新的DataTemplate
而不是重新使用现有的DataTemplate
。
答案 0 :(得分:4)
使用调度程序和一些低优先级的问题是,没有真正保证代码何时执行。您希望确保在UI更新后执行运行缓慢的代码。 A可以想到一个非常黑客的方法来做到这一点......
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();
以上内容创建了一个单一的&#39; tick&#39;在100毫秒后执行的计时器。