简体   繁体   English

C# WPF 如何在向 Stackpanel 添加许多 UI 元素的同时保持应用程序响应

[英]C# WPF How to keep Application responsive while adding many UI Elements to Stackpanel

I made an Application where I add many Grids to some Stackpanels in a for loop.我制作了一个应用程序,我在 for 循环中将许多网格添加到一些 Stackpanel 中。 My problem is that, while the for loop is loading my Application doesn´t respond and my Loadinganimation is freezed.我的问题是,当 for 循环加载时,我的应用程序没有响应并且我的 Loadinganimation 被冻结。 How can I add the Grids to the Stackpanel without affecting the UI Thread, so my Loading Animation won´t freeze.如何在不影响 UI 线程的情况下将网格添加到 Stackpanel,以便我的加载动画不会冻结。

Thanks in Advance提前致谢

Edit:编辑:

Grid creation Method:网格创建方法:

        public void GridExample()
        {
            for(int i = 0; i < 120; i++)
            {
                Grid Grid1 = new Grid();
                Grid1.FlowDirection = FlowDirection.LeftToRight;
                Grid1.Width = 200;
                Grid1.Background = new SolidColorBrush(Color.FromArgb(255, (byte)33, (byte)33, (byte)33));
                Grid1.Margin = new Thickness(5, 20, 5, 20);

                ColumnDefinition Grid1_col1 = new ColumnDefinition();
                Grid1.ColumnDefinitions.Add(Grid1_col1);

                RowDefinition Grid1_row1 = new RowDefinition();
                RowDefinition Grid1_row2 = new RowDefinition();
                RowDefinition Grid1_row3 = new RowDefinition();
                RowDefinition Grid1_row4 = new RowDefinition();
                Grid1.RowDefinitions.Add(Grid1_row1);
                Grid1.RowDefinitions.Add(Grid1_row2);
                Grid1.RowDefinitions.Add(Grid1_row3);
                Grid1.RowDefinitions.Add(Grid1_row4);

                Grid1_row1.Height = new GridLength(255);
                Grid1_row2.Height = new GridLength(60);
                Grid1_row3.Height = new GridLength(5);
                Grid1_row4.Height = new GridLength(55);


                //Adds Grid to HomePage
                homepage1_mainstackpanel1.Children.Add(Grid1);

                Image Image1 = new Image();
                Image1.Stretch = Stretch.Fill;
                Image1.Source = new BitmapImage(new Uri("Image.png"));
                Grid.SetRow(Image1, 0);
                Grid1.Children.Add(Image1);


                Label Label1 = new Label();
                Label1.Content = "Example Text";
                Label1.FontSize = 15;
                Label1.Foreground = new SolidColorBrush(Colors.White);
                Label1.VerticalAlignment = VerticalAlignment.Center;
                Label1.HorizontalAlignment = HorizontalAlignment.Center;
                Grid.SetRow(Label1, 1);
                Grid1.Children.Add(Label1);


                Line Line1 = new Line();
                Line1.X1 = 1;
                Line1.StrokeThickness = 2;
                Line1.Stroke = new SolidColorBrush(Color.FromArgb(255, (byte)51, (byte)51, (byte)51));
                Line1.Stretch = Stretch.Fill;
                Grid.SetRow(Line1, 2);
                Grid1.Children.Add(Line1);


                Button Button1 = new Button();
                Button1.Content = "Play";
                Button1.FontSize = 15;
                Button1.Foreground = new SolidColorBrush(Colors.White);
                Button1.Background = new SolidColorBrush(Color.FromArgb(255, (byte)33, (byte)33, (byte)33));
                Button1.BorderThickness = new Thickness(0);
                Button1.VerticalAlignment = VerticalAlignment.Center;
                Button1.HorizontalAlignment = HorizontalAlignment.Center;
                Button1.Click += new RoutedEventHandler((sender, e) =>
                {
                    this.NavigationService.Navigate(new WatchPage1());
                });
                Grid1.Children.Add(Button1);

            }
        }

Loading Animation in HomePage:在主页中加载动画:

public static Dispatcher mainthread_dispatcher = Dispatcher.CurrentDispatcher;

        public HomePage1()
        {
            Loaded += Page_loaded;
            InitializeComponent();
        }

        private void Page_loaded(object sender, RoutedEventArgs e)
        {
            using (LoadingAnimation loadanimation = new LoadingAnimation(GridExample))
            {
                loadanimation.ShowDialog();
            }
        }

LoadingAnimation.xaml:加载动画.xaml:

<Window x:Class="Spaceflix_Desktop.LoadingAnimation"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Spaceflix_Desktop"
             mc:Ignorable="d" 
             Height="110" Width="90" Loaded="Animation_Loaded">

    <Window.Resources>
        <Storyboard x:Key="Storyboard1" RepeatBehavior="Forever">
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse1">
                <EasingColorKeyFrame KeyTime="0" Value="#B25B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="#B25B5B5B"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse2">
                <EasingColorKeyFrame KeyTime="0" Value="#FF5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#7F5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="#FF5B5B5B"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse3">
                <EasingColorKeyFrame KeyTime="0" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#B25B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse4">
                <EasingColorKeyFrame KeyTime="0" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#7F5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse5">
                <EasingColorKeyFrame KeyTime="0" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#B25B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#005B5B5B"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse6">
                <EasingColorKeyFrame KeyTime="0" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#FF5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#7F5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="#005B5B5B"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse7">
                <EasingColorKeyFrame KeyTime="0" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#B25B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="#005B5B5B"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse8">
                <EasingColorKeyFrame KeyTime="0" Value="#7F5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#005B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="sc#0, 0.104616486, 0.104616486, 0.104616486"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#FF5B5B5B"/>
                <EasingColorKeyFrame KeyTime="0:0:1.4" Value="#7F5B5B5B"/>
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>

   
    <Window.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
        </EventTrigger>
    </Window.Triggers>


        <Border x:Name="Border" BorderBrush="#c62828" BorderThickness="2" Background="Black" Height="80" Width="80">
            <Grid x:Name="maingrid" Background="Transparent">
                <Ellipse x:Name="ellipse1" Fill="#FF5B5B5B" HorizontalAlignment="Center" Margin="0, 5, 0, 0" Height="15" VerticalAlignment="Top" Width="15"/>
                <Ellipse x:Name="ellipse2" Fill="#FF5B5B5B" HorizontalAlignment="Right" Margin="0, 15, 15, 0" Height="15" VerticalAlignment="Top" Width="15"/>
                <Ellipse x:Name="ellipse3" Fill="#FF5B5B5B" HorizontalAlignment="Right" Margin="0, 0, 5, 0" Height="15" VerticalAlignment="Center" Width="15"/>
                <Ellipse x:Name="ellipse4" Fill="#FF5B5B5B" HorizontalAlignment="Right" Margin="0, 0, 15, 15" Height="15" VerticalAlignment="Bottom" Width="15"/>
                <Ellipse x:Name="ellipse5" Fill="#FF5B5B5B" HorizontalAlignment="Center" Margin="0, 0, 0, 5" Height="15" VerticalAlignment="Bottom" Width="15"/>
                <Ellipse x:Name="ellipse6" Fill="#FF5B5B5B" HorizontalAlignment="Left" Margin="15, 0, 0, 15" Height="15" VerticalAlignment="Bottom" Width="15"/>
                <Ellipse x:Name="ellipse7" Fill="#FF5B5B5B" HorizontalAlignment="Left" Margin="5, 0, 0, 0" Height="15" VerticalAlignment="Center" Width="15"/>
                <Ellipse x:Name="ellipse8" Fill="#FF5B5B5B" HorizontalAlignment="Left" Margin="15, 15, 0, 0" Height="15" VerticalAlignment="Top" Width="15"/>
            </Grid>
        </Border>

</Window>

LoadingAnimation.cs:加载Animation.cs:

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Threading;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
using System.Runtime.Remoting.Channels;
using System.Windows.Media.Media3D;
using System.Windows.Interop;

namespace Test_Application
{
    /// <summary>
    /// Interaktionslogik für LoadingAnimation.xaml
    /// </summary>

    public partial class LoadingAnimation : Window, IDisposable
    {
        public Action Worker { get; set; }

        public LoadingAnimation (Action worker)
        {
            InitializeComponent();

            Worker = worker ?? throw new ArgumentNullException();
        }

        public void Animation_Loaded(object sender, RoutedEventArgs e)
        {
            Task.Factory.StartNew(() => { }).ContinueWith(t => HomePage1.mainthread_dispatcher.Invoke(() => Worker()), TaskScheduler.FromCurrentSynchronizationContext()).ContinueWith(t => Dispatcher.Invoke(() => Close()));
        }

        public void Dispose()
        {
        }
    }
}

I hope this Information are enough我希望这些信息足够了

after I didn't have time for this project for a long time, I've now dealt with it again and found a solution.在我很久没有时间做这个项目之后,我现在再次处理它并找到了解决方案。 I can't add the grids to the stack panels in a new task or thread but at least I can display the loading animation smoothly.我无法在新任务或线程中将网格添加到堆栈面板,但至少我可以流畅地显示加载动画。 Because the grids have to be added to the main thread, I ran the loading animation in a new thread.因为网格必须添加到主线程中,所以我在一个新线程中运行加载动画。 So I had to display it as a popup.所以我不得不将它显示为一个弹出窗口。 This is the best solution I found.这是我找到的最好的解决方案。

Here is the Code from the HomePage:这是主页上的代码:

        var PositionWindow = (Window)Parent;
        int CenterX = 8;
        int CenterY = 1;
        Point CenterPoints = new Point(PositionWindow.Left + CenterX + (PositionWindow.Width / 2), PositionWindow.Top + CenterY + (PositionWindow.Height / 2));

        Thread LoadThread = new Thread(new ThreadStart(() => {
            using (PopUpLoadingAnimation loadanimation = new PopUpLoadingAnimation(GridExample, CenterPoints, PositionWindow))
            {
                loadanimation.StartTask();
                Dispatcher.Run();
            }
        }));
        LoadThread.SetApartmentState(ApartmentState.STA);
        LoadThread.Start();

I had to calculate the middle of the Window by myself to make the PopUp centered.我必须自己计算 Window 的中间位置才能使 PopUp 居中。

And here is the Code of the PopUpLoadingAnimation.cs:这是 PopUpLoadingAnimation.cs 的代码:

public partial class PopUpLoadingAnimation : Popup
{
    public Action Worker { get; set; }
    private Point _PlacementPoints { get; set; }
    private Window MainWindow { get; set; }


    public PopUpLoadingAnimation (Action worker, Point PlacementPoints, Window mainthreadwindow)
    {
        InitializeComponent();

        Worker = worker ?? throw new ArgumentNullException();
        MainWindow = mainthreadwindow;
        _PlacementPoints = PlacementPoints;
    }

    public void StartTask()
    {
        Task.Factory.StartNew(() => Dispatcher.Invoke(() => 
        {
            Storyboard animationboard = Resources["Storyboard1"] as Storyboard;
            animationboard.Begin(maingrid);

            LoadingPopup.Placement = PlacementMode.Center;
            LoadingPopup.HorizontalOffset = _PlacementPoints.X;
            LoadingPopup.VerticalOffset = _PlacementPoints.Y;
            LoadingPopup.IsOpen = true;

            HomePage1.mainthread_dispatcher.Invoke(() => MainWindow.IsEnabled = false);

        })).ContinueWith(t => HomePage1.mainthread_dispatcher.Invoke(() => Worker()), HomePage1.mainthread_scheduler).ContinueWith(t => Dispatcher.Invoke(async () => 
        {
            LoadingPopup.IsOpen = false;
            HomePage1.mainthread_dispatcher.Invoke(() => MainWindow.IsEnabled = true);
            Dispatcher.InvokeShutdown(); 
        }));
    }

by the way thanks for the answers, unfortunately they did not help顺便感谢您的回答,不幸的是他们没有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何调用将UI元素从WPF C#应用程序中的主线程加载到不同堆栈面板的函数 - How to call a function that loads UI elements to different stackpanel from the main thread in WPF C# application C#WPF:将自定义用户控件添加到Stackpanel - C# WPF: Adding custom Usercontrol to Stackpanel 在 Xamarin C# 中向 UI 添加网格时保持响应式 UI - Keeping a responsive UI while adding Grids to the UI in Xamarin C# 从WPF / C#中的UserControl将子项添加到父窗口中的StackPanel中 - Adding Children to StackPanel in Parent Window from UserControl in WPF/C# C#WPF Stackpanel布局 - C# WPF Stackpanel layout 如何在为 c# WPF 中的 ui 保留一个的同时运行许多计算繁重的后台线程 - how to run many backgroundthreads whith heavy computation while reserving one for the ui in c# WPF 在将多个UIElements添加到画布时,如何保持UI响应? - How do I keep the UI responsive when adding many UIElements to a canvas? 如何以编程方式在C#中创建WPF可滚动StackPanel列表 - How to programmatically create WPF scrollable StackPanel list in C# 如何根据C#WPF中的条件将WPFUserControl添加到StackPanel - how to add WPFUserControl to a StackPanel depending on condition in C# WPF 如何在 C# 中传输数据包时正确保持 UI 更新? - How to properly keep the UI updated while transferring packets in C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM