簡體   English   中英

UI處於阻止狀態時,C#WPF顯示和加載指示器

[英]C# WPF Displaying and loading indicator while the UI is Blocked

我最近在這里仔細閱讀了許多帖子,以找到解決我問題的方法,但其中有8個被認為可以正常工作。

所以這是我的問題:我有一個很長的加載函數,要在其中遍歷Object幾次。 (主要是因為我必須找到孩子和孩子們的孩子...)

Funktion在大多數情況下都有效,但是即使我嘗試了盡可能多地使用線程並預加載巨大的DataTable,它的運行速度還是很慢的。

最大的問題是,我生成了UserControls,從而生成了更多相互關聯的UserControl。

Mabe這將有助於:
-遍歷所有對象,並找到具有parent = null的對象
-然后遍歷所有具有parent = null的“孩子”,並將其插入scrollviewer
-每個插入的子代將搜索自己的子代,並在它們自己的元素中的stackPanel中生成另一個概覽。

所有這些渲染/計算都需要一些時間,並且在運行時,用戶會看到一個灰色的窗口,因為我正在“ Window.loaded()”函數中調用此函數。

我現在想做的是顯示一個環或圖像,然后在將所有這些圖形元素添加到主窗口時旋轉它。

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函數中,但是隨后我對“ RoomOverview ro = new RoomOverview”和“ RefrigeratorOverview ro = new RefrigeratorOverview”的調用給我一個錯誤,因為他們無法在主窗體中添加任何內容,因為它屬於到另一個線程。

我希望任何人都能理解我在這里要做的事情,並希望知道解決方案。

最好的祝福
亞歷克斯

看來RoomOverviewRefrigeratorOverview是控件。 如果是這樣,那不是使用WPF的好方法。 請考慮學習MVVM。 它使這種事情變得容易得多。 必須處理混合了數據庫內容和UI控件的代碼,這是非常痛苦的。 理想情況下,您應該編寫一個執行數據庫工作並返回普通C#類實例的集合的方法。 然后,將它們放入綁定到ItemsControl或其他東西的ObservableCollection ,並使用為您創建所有UI控件的DataTemplate

但是,如果您不想進行重新設計,則可以挽救已有的產品。

嘗試將所有進程放在另一個線程中。

然后,要觸摸UI線程中的控件,您需要“調用UI線程”,這意味着從工作線程內部可以使代碼在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);
}));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM