WPF递增绑定属性在for循环中没有通知UI,并阻塞了它
本文关键字:UI 通知 绑定 属性 循环 for WPF | 更新日期: 2023-09-27 18:08:01
我使用wpf和mvvm有非常奇怪的问题。假设你有一个textbox
绑定到视图模型上的Counter
属性。按钮在视图模型上改变属性,引发PropertyChanged
事件,UI被更新。好吧,这正是发生了什么,如果我做的东西像Counter++
但是,当我尝试这样做在for循环,改变Counter
属性10次一次点击,它阻塞UI和显示只是最后一个字符串在循环结束…下面是代码:
public class MainViewModel : INotifyPropertyChanged
{
private int counter;
public int Counter
{
get { return counter; }
set { counter = value; Notify("Counter"); }
}
public MainViewModel()
{
Counter = 0;
}
public void inc()
{
for (int i = 0; i < 10000; i++)
{
Counter++;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var dataContext = button.DataContext as MainViewModel;
dataContext.inc();
}
}
<Window x:Class="WpfTests.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:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/prototyping/2010/interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTests"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel></local:MainViewModel>
</Window.DataContext>
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="40,106,0,0" TextWrapping="Wrap" Text="{Binding Counter}" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="287,106,0,0" VerticalAlignment="Top" Width="75" Click="button_Click">
</Button>
</Grid>
好吧,这就是发生的事情,如果我做类似于Counter++但是,当我尝试在for循环中这样做时,一次点击改变Counter属性10次,它会阻塞UI并在循环结束时显示最后一个字符串
当你改变Counter属性时,你是在UI线程中做的。在此期间,UI线程被阻塞。当第一次更改完成后,您将再次更新Counter属性=> UI线程再次阻塞。