2012-08-17 163 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"]; 
      } 
      )); 
}