6

オブジェクトのプロパティにソースがバインドされたImageコントロールがあります(画像への文字列URL)。サービスコールを行った後、データオブジェクトを新しいURLで更新します。例外は、PropertyChangedイベントを呼び出した後、コードを離れた後にスローされます。

データ構造とサービスロジックはすべて、UIの知識がないコアdllで実行されます。ディスパッチャにアクセスできない場合、UIスレッドと同期するにはどうすればよいですか?

PS:ルートビジュアルが別のスレッドにあるため、ディスパッチャーにアクセスするためにApplication.Current.RootVisualにアクセスすることは解決策ではありません(防止する必要がある正確な例外が発生します)。

PPS:これは画像コントロールの問題であり、他のUI要素へのバインドであり、クロススレッドの問題は自動的に処理されます。

4

6 に答える 6

7
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => {...});

こちらもご覧ください。

于 2009-12-18T18:08:07.507 に答える
1

INotifyPropertyChangedを実装してみましたか?

于 2008-09-06T06:37:10.277 に答える
0

これと同様の問題に遭遇しましたが、これは Windows フォームにありました。

別のプロセスに関する統計を更新する独自のスレッドを持つクラスがあり、UI にはこのオブジェクトにデータバインドされたコントロールがあります。クロススレッド呼び出しの問題が発生していました。これを解決した方法は次のとおりです。

Form m_MainWindow; //Reference to the main window of my application
protected virtual void OnPropertyChanged(string propertyName)
{
  if(PropertyChanged != null)
    if(m_MainWindow.InvokeRequired)
      m_MainWindow.Invoke(
        PropertyChanged, this, new PropertyChangedEventArgs(propertyName);
    else
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}

これはうまくいくようです。誰か提案があれば教えてください。

于 2009-08-11T16:36:26.100 に答える
0

Application クラスの RootVisual のプロパティ ゲッターには、その例外を引き起こすスレッド チェックがあります。App.xaml.cs の独自のプロパティにルート ビジュアルのディスパッチャーを格納することで、これを回避しました。

public static Dispatcher RootVisualDispatcher { get; set; }

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new Page();
    RootVisualDispatcher = RootVisual.Dispatcher;
}

次に、Application.Current.RootVisual.Dispatcher ではなく App.RootVisualDispatcher で BeginInvoke を呼び出した場合、この例外は発生しません。

于 2009-01-01T08:20:29.943 に答える
0

インターフェイスは、INotifyPropertyChangedプロパティ値が変更されたことをクライアント (通常はバインディング クライアント) に通知するために使用されます。

たとえば、FirstName というプロパティを持つ Person オブジェクトについて考えてみます。一般的なプロパティ変更通知を提供するために、Person 型は INotifyPropertyChanged インターフェイスを実装し、FirstName が変更されたときに PropertyChanged イベントを発生させます。

バインドされたクライアントとデータ ソースの間のバインドで変更通知が発生するようにするには、バインドされた型が次のいずれかである必要があります。

インターフェイスを実装しINotifyPropertyChangedます (推奨)。

バインドされた型の各プロパティに変更イベントを提供します。

両方を行わないでください。

例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

// Change the namespace to the project name. 
namespace TestNotifyPropertyChangedCS
{
    // This form demonstrates using a BindingSource to bind 
    // a list to a DataGridView control. The list does not 
    // raise change notifications. However the DemoCustomer type  
    // in the list does. 
    public partial class Form1 : Form
    {
        // This button causes the value of a list element to be changed. 
        private Button changeItemBtn = new Button();

        // This DataGridView control displays the contents of the list. 
        private DataGridView customersDataGridView = new DataGridView();

        // This BindingSource binds the list to the DataGridView control. 
        private BindingSource customersBindingSource = new BindingSource();

        public Form1()
        {
            InitializeComponent();

            // Set up the "Change Item" button.
            this.changeItemBtn.Text = "Change Item";
            this.changeItemBtn.Dock = DockStyle.Bottom;
            this.changeItemBtn.Click +=
                new EventHandler(changeItemBtn_Click);
            this.Controls.Add(this.changeItemBtn);

            // Set up the DataGridView.
            customersDataGridView.Dock = DockStyle.Top;
            this.Controls.Add(customersDataGridView);

            this.Size = new Size(400, 200);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Create and populate the list of DemoCustomer objects 
            // which will supply data to the DataGridView.
            BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();
            customerList.Add(DemoCustomer.CreateNewCustomer());
            customerList.Add(DemoCustomer.CreateNewCustomer());
            customerList.Add(DemoCustomer.CreateNewCustomer());

            // Bind the list to the BindingSource. 
            this.customersBindingSource.DataSource = customerList;

            // Attach the BindingSource to the DataGridView. 
            this.customersDataGridView.DataSource =
                this.customersBindingSource;

        }

        // Change the value of the CompanyName property for the first  
        // item in the list when the "Change Item" button is clicked.
        void changeItemBtn_Click(object sender, EventArgs e)
        {
            // Get a reference to the list from the BindingSource.
            BindingList<DemoCustomer> customerList =
                this.customersBindingSource.DataSource as BindingList<DemoCustomer>;

            // Change the value of the CompanyName property for the  
            // first item in the list.
            customerList[0].CustomerName = "Tailspin Toys";
            customerList[0].PhoneNumber = "(708)555-0150";
        }

    }

    // This is a simple customer class that  
    // implements the IPropertyChange interface. 
    public class DemoCustomer : INotifyPropertyChanged
    {
        // These fields hold the values for the public properties. 
        private Guid idValue = Guid.NewGuid();
        private string customerNameValue = String.Empty;
        private string phoneNumberValue = String.Empty;

        public event PropertyChangedEventHandler PropertyChanged;

        // This method is called by the Set accessor of each property. 
        // The CallerMemberName attribute that is applied to the optional propertyName 
        // parameter causes the property name of the caller to be substituted as an argument. 
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        // The constructor is private to enforce the factory pattern. 
        private DemoCustomer()
        {
            customerNameValue = "Customer";
            phoneNumberValue = "(312)555-0100";
        }

        // This is the public factory method. 
        public static DemoCustomer CreateNewCustomer()
        {
            return new DemoCustomer();
        }

        // This property represents an ID, suitable 
        // for use as a primary key in a database. 
        public Guid ID
        {
            get
            {
                return this.idValue;
            }
        }

        public string CustomerName
        {
            get
            {
                return this.customerNameValue;
            }

            set
            {
                if (value != this.customerNameValue)
                {
                    this.customerNameValue = value;
                    NotifyPropertyChanged();
                }
            }
        }

        public string PhoneNumber
        {
            get
            {
                return this.phoneNumberValue;
            }

            set
            {
                if (value != this.phoneNumberValue)
                {
                    this.phoneNumberValue = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
}
于 2013-08-15T05:40:05.043 に答える