初始化大量UserControl而不冻结GUI

时间:2019-02-20 16:44:32

标签: c# wpf mvvm

通过单击button,创建了大量(约200个)UserControl(按照ItemsControl原理将集合绑定到MVVM),如下所示:结果是应用程序冻结了5秒钟。是否可以使此过程轻松进行?目前,在创建循环中,我使用Task.Delay (100);,该应用程序会挂起一些,但可以继续工作。

使用:

<ItemsControl ItemsSource="{Binding Path=CurrentSession.Messages}" Background="Transparent" BorderThickness="0">
  <ItemsControl.ItemTemplate>
     <DataTemplate>
       <local:ChatMessageControl/>
     </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

XAML UserControl :(此控件中使用的其他集合被禁用。它们仅在XAML中,并且在测试期间始终为空)

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="70"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="10"/>
        </Grid.RowDefinitions>
        <Grid Grid.Column="0">
            <Border Height="45" Width="45" CornerRadius="50,50,50,50" Visibility="{Binding NeedIcon}" VerticalAlignment="Top" Margin="0 10">
                <Border.Background>
                <ImageBrush ImageSource="{Binding Icon, FallbackValue={StaticResource DefaultImage},
                                TargetNullValue={StaticResource DefaultImage}}"/>
            </Border.Background>
        </Border>
         </Grid>
        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <StackPanel Orientation="Vertical">
                <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0 2 0 0" Visibility="{Binding NeedIcon}">
                    <TextBlock Text="{Binding Name,FallbackValue=Name}" Foreground="White" FontSize="16" Margin="10 10 10 0"/>
                    <TextBlock Text="{Binding Time, FallbackValue=0:00}" Foreground="#bdbebd" HorizontalAlignment="Center" Margin="0 10" />
                </StackPanel>
                <TextBlock Grid.Row="0" Text="{Binding Message,FallbackValue=Text}" HorizontalAlignment="Left" FontSize="14" Visibility="{Binding HasMessage, Converter={StaticResource converter}}" TextWrapping="Wrap" Margin="10 0 0 0"/>
                <StackPanel Grid.Row="1" Visibility="{Binding HasImage, Converter={StaticResource converter}}" HorizontalAlignment="Left" Margin="0 10">
                    <ItemsControl ItemsSource="{Binding Images}" Background="Transparent" BorderThickness="0" Margin="10 0 0 0">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <UniformGrid Columns="3" MaxWidth="600"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <local:ImageUserControl/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>
                <StackPanel Grid.Row="1" Visibility="{Binding HasOtherDocs, Converter={StaticResource BoolToVis}}">
                    <local:OtherDocsUserControl DataContext="{Binding OtherDocs}"/>
                </StackPanel>
                <StackPanel Grid.Row="2" Margin="0 5" Visibility="{Binding HasAudio, Converter={StaticResource BoolToVis}}" HorizontalAlignment="Left">
                    <ItemsControl ItemsSource="{Binding Audios}" Background="Transparent" BorderThickness="0" Margin="10 0 0 0">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <local:AudioMessageUserControl/>
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>
            </StackPanel>
        </Grid>

Loop.Event订阅

private async void AddMessages(List<DialogMessageModel> msg)
        {
            App.Current.Dispatcher.Invoke((Action)async delegate
            {
                msg.Reverse();
                for (int i = 0; i < msg.Count; i++)
                {
                    await Task.Delay(50);
                        CurrentSession.Messages.Add(msg[i]);
                }
            });
        }

1 个答案:

答案 0 :(得分:-2)

您可以尝试实现一种Application.DoEvents()-在WPF中已弃用- 我建议您使用BackgroundWorkerDispatcher

public static void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
                                          new Action(delegate { }));
}