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"];

    }

イベントを発生させるパスにファイルが作成されるとすぐに、次のエラーが表示されます: Invalid operation exception 別のスレッドが所有しているため、呼び出しスレッドはこのオブジェクトにアクセスできません。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"];
            }
        ));

了解しました コメントありがとうございます

4

3 に答える 3

1

WPFでは、アプリケーションが別のスレッドで実行されている間、すべてのUIコントロールが別のスレッドに読み込まれます。

したがって、アプリケーション(メインスレッド)がUIThreadにあるElipseにアクセスしようとしているため、このエラーが発生していると考えてください。また、スレッドは相互のオブジェクトに直接アクセスできないため、これは許可されていません。

そのため、WPFはディスパッチャオブジェクトを導入しました。以下を使用してください

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"];
            }
            ));
}
于 2012-08-17T12:07:46.993 に答える
1

UI 要素には、それらが作成されたのと同じスレッドからのみアクセスできます。

UI スレッドでデリゲートを呼び出すには、Dispatcher.Invoke または Dispatcher.BeginInvoke を使用する必要があります。その後、「作成された」要素の「Fill」プロパティにアクセスできます。

問題の説明については、次のリンクを参照してください。

UI で変化する色を設定しようとする代わりに、状態を保持する ViewModel のプロパティを公開することができます。

FileWatcher が (watcherCreated メソッドを呼び出して) 新しく作成されたファイルを通知したら、ViewModel でその状態を設定するだけです。

UI で... Binding と Converter を使用して、ViewModel の状態プロパティにバインドします。コンバーターは、状態に応じて使用するブラシを決定します。たとえば、状態が 1 の場合は緑のブラシを返し、状態が 0 の場合は赤のブラシを返します。

状態を「オフ」の位置にリセットするには...たとえば1秒後に状態値をオフに戻すタイマーを設定できます。

これを行うことで....状態を UI から分離します。

将来、UI で状態を表示するためのより洗練された方法が必要な場合...たとえば、緑から赤に徐々にフェードアウトするアニメーション (StoryBoards/Visual State Manager を使用) が必要な場合は、そのアニメーションを使用できます。再び ViewModel の状態に基づいてトリガーされます。

于 2012-08-17T12:00:18.993 に答える
0

さらに簡単な解決策は、UI スレッド自体に created.Fill を設定することです。Dispatcher.Invoke または Dispatcher.BeginInvoke は必要ありません。

于 2012-08-17T12:05:02.680 に答える