Вот моя проблема.
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, похоже, заблокирована этой задержкой DataBinding. В результате пользовательский интерфейс «встает» на место, и моя гладкая StoryBoard не видна.
Я решил эту проблему, подключившись к событию StoryBoard.Completed. Как только StoryBoard готов, я устанавливаю ItemsSource для ListBox B.
Однако это хорошо только на 50%. Да, пользователь видит выполнение StoryBoard. Но полученный пользовательский интерфейс ListBox B по-прежнему «привязывается» к виду после анимации.
Мне кажется, что правильное разрешение - это каким-то образом указать элементам управления, отображаемым внутри ListBox B, ждать или задерживать фактическую привязку данных. Это позволит отображать пользовательский интерфейс и участвовать в StoryBoard - но данные будут «заполнены» позже (надеюсь, также задерживая задержку, вызванную DataBinding).
У кого-нибудь была подобная проблема?
Вот 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>
Выглядит так:
Спасибо!