Is there a way to defer WPF DataBinding (improve rendering)?

Here is my problem.

ListBox A displays all the items in the observed collection.

ListBox B shows only those items that are selected in ListBox A.

<ListBox ItemsSource="{Binding MyView}" Name="ListBoxA"> <ListBox ItemsSource="{Binding Path=SelectedItems, ElementName=ListBoxA}" Name="ListBoxB"> 

When a selection changes in ListBox A, the StoryBoard starts. As a result, the user interface is a cool and smooth slide in and out of ListBox B based on user selection.

The problem is that in my ListBox A specification there are only the Name property, the DataBox B databinds have dozens, and in some cases even hundreds of properties.

The problem continues that data binding in WPF creates a short user interface delay of 50-500 milliseconds when rendering it (in particular, when it is dynamic). The user interface freezes.

It is possible. But my StoryBoard seems to be blocked by this DataBinding delay. As a result, the user interface β€œsnaps” in place and my sleek StoryBoard is not visible.

I resolved this by joining the StoryBoard.Completed event. After completing the StoryBoard, I install the ItemSource for ListBox B.

However, this is only 50%. Yes, the user sees that the StoryBoard is running. But the resulting UI ListBox B still β€œsnaps” after watching the animation.

It seems to me that the correct resolution is to somehow point to the controls displayed inside ListBox B to wait or delay the actual data binding. This will allow you to display the user interface and participate in the StoryBoard, but the data to β€œpopulate” is later (I hope this also delays the delay caused by the DataBinding).

Has anyone had a similar problem?

Here's the XAML that demonstrates the problem exactly (since StackOverflow limits the size of the question, you will need to add additional TextBoxes to actually see the delay):

 <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> 

It looks like:

enter image description here

Thanks!

+6
source share
2 answers

There is no way to deal with this except to minimize the number of visible elements in the resulting control. Of course, you can also buy a large computer, but this is only a joke.

0
source

I have never had such problems before, and as far as I know, there is no built-in way to delay data binding in WPF.

I tried my code with 1000+ textbox inside ListboxB. ListboxB is pretty fast, but if you still want to reduce the rendering time for ListboxB, you can try adding the code below to ListboxB.

 VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" 

This will only create the controls inside the ListBoxB that are currently visible, which will improve the rendering of the ListBoxB.

You can check out my article on VirtualizingStackPanel .

Hope this answer helps you.

+4
source

Source: https://habr.com/ru/post/893105/


All Articles