2014-12-29 115 views
1

我想改变使用C#的WPF按钮的颜色。WPF属性没有立即反映(只反映最后的变化)

比方说,我有一个WPF按钮,我想改变为1秒,其颜色:

<Button Name="Button1"></Button> 

我也有一个按钮,用于启动一个变化:

<Button Name="ProcessControl" Click="ProcessControl_Click">Start</Button> 

我有C#代码不作任何可见的变化:

private void ProcessControl_Click(object sender, RoutedEventArgs e) 
{ 
     Brush background = button.Background; 
     Button1.Background = System.Windows.Media.Brushes.Yellow; 
     Thread.Sleep(1000); 
     Button1.Background = background; 
} 

但是,如果我会写这个代码,哪个cha nges颜色,不等待第二个,它不会恢复旧的颜色,它的工作原理:

private void ProcessControl_Click(object sender, RoutedEventArgs e) 
{ 
     Brush background = button.Background; 
     Button1.Background = System.Windows.Media.Brushes.Yellow; 
} 

这是一个与所有WPF元素和属性同样的事情。如果某些属性发生了两次更改,只有最后一次更改才会反映出来

我也试着拨打:

this.UpdateLayout(); 

,但它不解决问题。

我试过使用后台工作,但它也不能解决我的问题。

现在是否有人如何立即反映使用C#的WPF中的属性更改?

+1

这很可能是你的'线程。睡眠(1000)'会阻塞UI线程,因此按钮不会以新颜色重新绘制。你应该使用动画来代替http://msdn.microsoft.com/en-us/library/ms752312%28v=vs.110%29.aspx –

回答

2

问题是您用Sleep阻止UI线程,这意味着无法呈现更新的属性。如果你使用的是支持异步版本/的await,可以转而尝试这个办法:

private async void ProcessControl_Click(object sender, RoutedEventArgs e) 
{ 
     Brush background = button.Background; 
     Button1.Background = System.Windows.Media.Brushes.Yellow; 
     await Task.Delay(1000); 
     Button1.Background = background; 
} 

这在UI线程上注册一个回调后一秒火(假设Click事件处理程序从UI叫除非手动调用该方法,否则它应该始终保持)。

+0

使用'await'就像这样感觉*错误*。它当然有用;好答案! – BradleyDotNET

+0

@BradleyDotNET,我喜欢使用'Task.Delay'作为在UI线程上注册一个定时器回调的简短版本;我现在几乎总是用这个代替明确的定时器。当然,拥有异步无效的方法并不是一个很好的做法;当你将上面的模式概括为生产代码时,你肯定必须留意在假设的情况下可能会改变你的应用程序状态(在睡眠UI线程时通常会被抑制)。这些相同的问题,虽然也许在等待时不那么明显。 –

0

第一个代码示例将不起作用,因为您用Thread.Sleep阻止了UI线程。基本上,你(在UI线程)

  1. 改变颜色
  2. 睡眠(注意UI一直没有机会尚未更新!)
  3. 更改颜色重新
  4. UI更新,到旧的颜色!

在后台工作人员这样做可工作如果你改变了颜色,然后睡在另一个线程的第二个变化。当然,这个改变将不得不被封送回UI线程,所以如果你不小心在Sleep的位置,你会看到相同的行为。

实际上,你应该改变颜色,然后设置一个计时器。在该计时器的Elapsed事件中,将颜色设回。您也可以使用async/await,以便UI线程不会阻塞,就像Dan Bryant的回答一样。