C#WPF在UI被阻止时显示和加载指示符

时间:2017-05-19 13:36:27

标签: c# wpf multithreading xaml

我最近在这里阅读了很多帖子,为我的问题找到了解决办法,但是他们中的一些人更加努力工作....

所以这就是我的问题: 我有一个很长的加载功能,我在Object列表中进行了几次。 (主要是因为我必须找到孩子的孩子和孩子......)

这个Funktion在大多数情况下都有效,但它变得有点慢,尽管我已尽可能多地尝试使用线程并加载大量DataTable。

最大的问题是,我生成了UserControls,它会生成更多相互串联的UserControl。

Mabe这将有所帮助:
- 遍历所有对象,找到parent = null的那些对象 - 然后去看看所有的孩子" with parent = null并将它们插入到scrollviewer中 - 每个插入的孩子都会搜索它自己的孩子,并在其中生成另一个概述到其自身元素中的stackPanel。

所有这些渲染/计算都需要一些时间,当它运行时,用户会看到一个灰色的窗口,因为我在我的" Window.loaded()&#34中调用了这个函数;功能

我现在要做的是,显示一个环或图像,并可能在所有这些图形元素添加到主窗口时旋转它。

private void getData() {
LoadingMessage lm = new LoadingMessage() { Owner = this };
Application.Current.Dispatcher.Invoke(() => { lm.Show(); });
tbLoading.Text += ".";
//dtRacks = Storage.getAllNormalRacks();
//DataTable dtparents = dtRacks.AsDataView().ToTable(true, "CONTENTOF");
bool hasRacks = false;

start = Storage.getStorageObject(parentID);

spRooms.Children.Clear();
tbHeader.Text = "Übersicht: " + start["DESCRIPTION"].ToString();


DataTable dtchilds = getChilds(parentID);

foreach (DataRow dr in dtchilds.Rows) {
    string type = dr["TYPE"].ToString();

    if (type == "8") {
        RoomOverview ro = new RoomOverview(dr["ID"].ToString(), dr["DESCRIPTION"].ToString(), search, this);
        foreach (Expander ex in ro.MainGrid.Children.OfType<Expander>()) {
            ex.IsExpanded = true;
        }
        ro.Padding = new Thickness(3, 0, 1, 0);
        if (ro.spFridges.Children.Count >= 1) spRooms.Children.Add(ro);

    }

    if (type == "1" || type == "2" || type == "3" || type == "4") {
        RefrigeratorOverview ro = new RefrigeratorOverview(dr["ID"].ToString(), dr["DESCRIPTION"].ToString(), search, this);
        ro.Padding = new Thickness(3, 0, 1, 0);
        if (ro.spStudies.Children.Count >= 1) spRooms.Children.Add(ro);
    }
    if (type == "5") hasRacks = true;
}

if (hasRacks) {
    RefrigeratorOverview ro = new RefrigeratorOverview(parentID, start["DESCRIPTION"].ToString(), search);
    ro.Padding = new Thickness(3, 0, 1, 0);
    if (ro.spStudies.Children.Count >= 1) spRooms.Children.Add(ro);
}

if (roots.Count > 0) {
    foreach (string s in roots) {
        RoomOverview ro = new RoomOverview(s, null, search, this);
        ro.Padding = new Thickness(3, 0, 1, 0);
        if (ro.spFridges.Children.Count >= 1) spRooms.Children.Add(ro);

    }
    tbLoading.Visibility = Visibility.Hidden;
    Application.Current.Dispatcher.Invoke(() => { lm.Close(); });
}
}

我尝试将整个功能整合到一个Threaded功能中,但随后我调用了#34; RoomOverview ro = new RoomOverview&#34;和&#34;冰箱概述ro =新冰箱概述&#34;给了我一个错误,因为他们无法向主表单添加任何内容,因为它属于另一个主题。

我希望任何人都能理解我在这里尝试做什么,并希望知道解决方案。

最好的问候 亚历

1 个答案:

答案 0 :(得分:0)

RoomOverviewRefrigeratorOverview似乎是控件。如果是这样,那不是使用WPF的好方法。请考虑学习MVVM。它使这种事情变得更容易。处理混合数据库内容和UI控件的代码非常痛苦。理想情况下,您应该编写一个方法来处理数据库内容并返回一组普通的C#类实例。然后,您将ObservableCollection绑定到ItemsControl或其他内容,并使用DataTemplate为您创建所有UI控件。

但如果你不想进行重新设计,你可以挽救你所得到的东西。

将您的所有进程放在另一个线程中,就像您尝试的那样。

然后要触摸UI线程中的控件,您需要调用UI线程&#34;这意味着从您的工作线程内部,您可以导致代码执行UI线程:

RoomOverview ro = null;
var id = dr["ID"].ToString();
var description = dr["DESCRIPTION"].ToString();

Dispatcher.CurrentDispatcher.Invoke(new Action(() => {
    ro = new RoomOverview(id, description, search, this);
    foreach (Expander ex in ro.MainGrid.Children.OfType<Expander>()) {
        ex.IsExpanded = true;
    }
    ro.Padding = new Thickness(3, 0, 1, 0);
    if (ro.spFridges.Children.Count >= 1) spRooms.Children.Add(ro);
}));