2012-08-17 109 views
0

我还没有使用wpf很多,并认为这将是一个简单的过程,在运行时改变椭圆的颜色。我有一个FileWatcher,并且在创建的事件中,我想将椭圆的颜色更改为颜色并再次返回,从而创建闪烁效果。 (创建为椭圆,BR4是在XAML定义纯色刷)在运行时改变椭圆颜色

public void watcherCreated(object seneder, FileSystemEventArgs e) 
    { 

     Application.Current.Resources["br4"] = new SolidColorBrush(Colors.Green); 
     created.Fill = (SolidColorBrush)Application.Current.Resources["br4"]; 

    } 

一旦一个文件被在其中引发事件我得到这个误差的路径中创建:无效操作异常 调用线程不能访问此对象,因为不同的线程拥有它。 我已经使用freeze()方法寻找解决方案,但没有成功。

 created.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
      delegate() 
      { 
       Application.Current.Resources["br4"] = new SolidColorBrush(Colors.Green); 
       created.Fill = (SolidColorBrush)Application.Current.Resources["br4"]; 
      } 
     )); 

得到它感谢意见

+0

参见[这](http://stackoverflow.com/a/1458032/773118)答案(WPF的部分)类似(完全一样?)的问题。 – Eirik 2012-08-17 12:03:02

回答

1

您只能从创建它们在同一个线程访问UI元素。

您应该使用Dispatcher.Invoke或Dispatcher.BeginInvoke在UI线程上调用一个委托...然后您可以在其中访问“已创建”元素的“Fill”属性。

请参阅此链接问题的解释:

而不是试图设置改变颜色的UI ......你可以做的是暴露在一个属性你的ViewModel拥有一个状态。

当FileWatcher通知您新创建的文件时(通过调用您的watcherCreated方法),您只需在ViewModel中设置该状态即可。

在您的用户界面中...使用绑定与转换器绑定到ViewModel中的状态属性。转换器将根据状态确定使用什么刷子,例如,如果状态为1,则返回绿色画笔,如果状态为0,则返回红色画笔。

要重置状态回“关”的位置......你可以有一个计时器,说1秒后,等...将状态值设置为关闭。

通过这样做,您可以将用户界面的状态分开。

如果将来您想要更复杂的方式来显示UI中的状态......例如,有一个动画(使用StoryBoards /视觉状态管理器)逐渐消失,从绿色回到红色......然后你可以让这个动画触发,再次基于ViewModel中的状态。

+0

我已经看到了一些这样的例子,认为会有一个简单的解决方案。我会再次看到这个谢谢 – 2012-08-17 12:02:10

0

更简单的解决方案是在UI线程本身上设置created.Fill。您将不需要Dispatcher.Invoke或Dispatcher.BeginInvoke。

1

In WPF all the UI controls are loaded in a different thread while as your application runs in a separate thread.

So , think it as , you are getting this error because your application(Main Thread) is trying to access the Elipse that is in UIThread. And this is not allowed for as threads can not access each others object directly.

So WPF has introduced dispatcher object. Use the following

if (this.Dispatcher.Thread != System.Threading.Thread.CurrentThread) 
{ 
    this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, 
     new Action(
      delegate() 
      { 
       Application.Current.Resources["br4"] = new SolidColorBrush(Colors.Green); 
       created.Fill = (SolidColorBrush)Application.Current.Resources["br4"]; 
      } 
      )); 
}