Dev*_*Dan 12 wpf binding wpf-controls inotifypropertychanged
每次循环迭代,我都想直观地更新文本块的文本.我的问题是WPF窗口或控件在循环完成之前不会直观刷新.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Run Code Online (Sandbox Code Playgroud)
在VB6中,我会打电话DoEvents()或control.Refresh.目前我只是喜欢类似的快速和肮脏的解决方案DoEvents(),但我也想了解替代方案或"正确"的方法来做到这一点.我可以添加一个简单的绑定语句吗?语法是什么?提前致谢.
Gre*_*som 26
如果您真的想要快速而肮脏的实现并且不关心将来维护产品或关于用户体验,您只需添加对System.Windows.Forms的引用并调用System.Windows.Forms.Application.DoEvents():
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
Run Code Online (Sandbox Code Playgroud)
缺点是它真的很糟糕.您将在Thread.Sleep()期间锁定UI,这会使用户烦恼,并且您可能最终得到不可预测的结果,具体取决于程序的复杂性(我已经看到一个应用程序,其中有两个方法在运行UI线程,每个都重复调用DoEvents()...).
这是一个显示您要求的功能的示例.它只需要几秒钟的时间来编写,并且它更容易使用 - 而且它不会锁定UI.
XAML:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
代码隐藏:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)
代码可能看起来有点复杂,但它是WPF的基石,它与一些练习结合在一起 - 非常值得学习.
我尝试了这里公开的解决方案,直到我添加以下内容后它才对我有效:
创建扩展方法并确保从项目中引用其包含的程序集.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Run Code Online (Sandbox Code Playgroud)
然后在之后立即调用RaisePropertyChanged:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
Run Code Online (Sandbox Code Playgroud)
这将迫使UI线程暂时控制并在UI元素上分派任何挂起的更改.