Вот моя проблема.
ListBox A показывает все элементы в наблюдаемой коллекции.
ListBox B показывает только те элементы, которые выбраны в ListBox A.
<ListBox ItemsSource="{Binding MyView}" Name="ListBoxA">
<ListBox ItemsSource="{Binding Path=SelectedItems,
ElementName=ListBoxA}" Name="ListBoxB">
Когда выбор изменяется в ListBox A, запускается StoryBoard. Получающийся пользовательский интерфейс представляет собой плавный и плавный ввод и вывод ListBox B в зависимости от выбора пользователя.
Проблема в том, что мои данные ListBox A связывают только свойство Name, данные ListBox B связывают десятки, а в некоторых случаях даже сотни свойств.
Проблема по-прежнему заключается в том, что привязка данных в WPF создает короткую задержку пользовательского интерфейса в 50-500 миллисекунд при рендеринге (особенно когда он динамический). Пользовательский интерфейс зависает.
Это ужасно. Но моя StoryBoard, кажется, заблокирована этой задержкой привязки данных. В результате пользовательский интерфейс "защелкивается", и моя гладкая StoryBoard не видна.
Я решил эту проблему, добавив событие StoryBoard.Completed. Когда StoryBoard завершен, я устанавливаю ItemsSource для ListBox B.
Однако это только на 50% приятнее. Пользователь видит выполнение StoryBoard, да. Но итоговый пользовательский интерфейс ListBox B все еще «защелкивается» после анимации.
Мне кажется, что правильное разрешение должно как-то указывать элементам управления, представленным внутри ListBox B, на ожидание или задержку фактической привязки данных. Это позволило бы отображать пользовательский интерфейс и участвовать в StoryBoard, но данные «заполнялись» позже (возможно, также задерживая задержку, вызванную привязкой данных).
У кого-нибудь была подобная проблема?
Вот XAML, который точно демонстрирует проблему (поскольку StackOverflow ограничивает размер вопроса, вам необходимо добавить дополнительные текстовые поля, чтобы реально увидеть задержку):
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="MyData">
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
<sys:String>Five</sys:String>
<sys:String>Six</sys:String>
</x:Array>
<Storyboard x:Key="MyGrowStoryboard">
<ParallelTimeline>
<DoubleAnimation To="1" DecelerationRatio="0.5"
Duration="00:00:00.500"
Storyboard.TargetName="MyTransform"
Storyboard.TargetProperty="ScaleX" />
<DoubleAnimation To="1" DecelerationRatio="0.5"
Duration="00:00:00.500"
Storyboard.TargetName="MyTransform"
Storyboard.TargetProperty="ScaleY" />
</ParallelTimeline>
</Storyboard>
<Storyboard x:Key="MyShrinkStoryboard">
<ParallelTimeline>
<DoubleAnimation To=".1" DecelerationRatio="0.5"
Duration="00:00:00.500"
Storyboard.TargetName="MyTransform"
Storyboard.TargetProperty="ScaleX" />
<DoubleAnimation To=".1" DecelerationRatio="0.5"
Duration="00:00:00.500"
Storyboard.TargetName="MyTransform"
Storyboard.TargetProperty="ScaleY" />
</ParallelTimeline>
</Storyboard>
</Page.Resources>
<StackPanel>
<ListBox ItemsSource="{Binding Source={StaticResource MyData}}"
Name="ListBoxA">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<DataTemplate.Triggers>
<!-- grow -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True"
Binding="{Binding Path=IsSelected,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}}}" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard
Storyboard="{StaticResource MyGrowStoryboard}" />
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard
Storyboard="{StaticResource MyShrinkStoryboard}" />
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
<!-- shrink -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="False"
Binding="{Binding Path=IsSelected,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}}}" />
<Condition Value="1"
Binding="{Binding Path=SelectedItems.Count,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBox}}}" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard
Storyboard="{StaticResource MyShrinkStoryboard}" />
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard
Storyboard="{StaticResource MyGrowStoryboard}" />
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</DataTemplate.Triggers>
<TextBlock Text="{Binding .}">
<TextBlock.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1"
x:Name="MyTransform"/>
</TextBlock.LayoutTransform>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Path=SelectedItems,
ElementName=ListBoxA}" Name="ListBoxB">
<ListBox.ItemTemplate>
<DataTemplate>
<UniformGrid Columns="10">
<!-- repeat this part MANY times (like 3000) ! -->
<TextBox Text="{Binding .}" />
<TextBox Text="{Binding .}" />
<TextBox Text="{Binding .}" />
<TextBox Text="{Binding .}" />
<TextBox Text="{Binding .}" />
</UniformGrid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Page>
выглядит так:
Спасибо!