我在我的公司使用 LabVIEW,并想更改為 C# MVVM。在我的自學之旅中,當我遇到一些在 LabVIEW 中很容易完成但在 C# 中無法完成的事情時,我覺得自己像個白癡。
了解 MVVM 基礎知識后,我現在試圖獲得一個簡單的進度條,顯示以 1000 毫秒為間隔的更新,直到已滿。但是當執行以下代碼時,視窗顯示一個空的進度條,并在 4 秒后跳轉到最終值 100。
我想我弄錯了一些絕對的基本編程原則,所以如果你能幫助我,我將不勝感激。提前致謝!!
以下是代碼:
主視窗.xaml
<Window x:Class="MicrosoftMVVMToolkit_Sandbox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MicrosoftMVVMToolkit_Sandbox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ProgressBar Width="500" Height="10" Value="{Binding Progress}" Minimum="0" Maximum="100"></ProgressBar>
</Grid>
主視窗.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Toolkit.Mvvm;
namespace MicrosoftMVVMToolkit_Sandbox
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ViewModel vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = vm;
this.Show();
vm.Work();
}
}
}
視圖模型.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm;
using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace MicrosoftMVVMToolkit_Sandbox
{
class ViewModel : ObservableObject
{
private int progress;
public int Progress
{
get => progress;
set => SetProperty(ref progress, value);
}
public void Work()
{
Progress = 0;
System.Threading.Thread.Sleep(1000);
Progress = 25;
System.Threading.Thread.Sleep(1000);
Progress = 50;
System.Threading.Thread.Sleep(1000);
Progress = 75;
System.Threading.Thread.Sleep(1000);
Progress = 100;
}
}
}
============================
解決方案 1 - 等待 Task.Delay 選項:
下面是 await Task.Delay 選項的示例代碼,以防其他人遇到同樣的問題:
public async void Work()
{
Progress = 0;
await Task.Delay(1000);
Progress = 25;
await Task.Delay(1000);
Progress = 50;
await Task.Delay(1000);
Progress = 75;
await Task.Delay(1000);
Progress = 100;
}
uj5u.com熱心網友回復:
這里的主要問題是進度條只有在 UI 執行緒未被阻塞時才能更新。即它正在處理 Windows 訊息。Thread.Sleep但是會阻塞 UI 執行緒,阻止它執行任何其他作業,包括繪制進度條。
有幾種可能的解決方案
- 使用異步方法并使用
await Task.Delay(1000)代替Thread.Sleep. 這將允許 UI 執行緒在等待時做其他作業。但是如果你需要做任何處理密集型的事情,它就行不通。 - 在后臺執行緒上運行您的作業,例如使用
Task.Run. 但這會導致下一個問題:不允許從后臺執行緒更新任何 UI 控制元件。為此,有兩種解決方案:- 用于
Dispatcher.BeginInvoke從 UI 執行緒更新 Progress 屬性。(或任何在 UI 執行緒上運行代碼的等效方法) - 從后臺執行緒更新進度欄位,但使用單獨的計時器來引發
OnPropertyChanged進度屬性的事件。計時器應該是在 UI 執行緒上運行的計時器,例如DispatchTimer. 這樣做的好處是允許頻繁的進度更新,而不會用訊息向 UI 執行緒發送垃圾郵件。
- 用于
uj5u.com熱心網友回復:
在建構式中:
public MainWindow()
{
InitializeComponent();
this.DataContext = vm;
this.Show();
vm.Work();
}
vm.Work()阻止您的代碼執行 4 秒(每次呼叫System.Threading.Thread.Sleep(1000))它使 UI 不負責那段時間。
您需要Progress使用一些非阻塞工具更改進度條,例如DispatcherTimer.
例子:
// remove vm.Work() from constructor
// add private field in MainWindow
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
// add in constructor
dispatcherTimer.Tick = dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();
// add private method in MainWindow
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
vm.Progress = 1;
}
我沒有測驗這段代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/349814.html
上一篇:執行flutterrun失敗
