Как получать уведомления об изменении свойства в форме при изменении свойства в классе?

У меня есть класс с интерфейсом INotifyPropertyChanged. Есть свойство с названием Total Progress.

У меня есть форма с индикатором выполнения. Я хочу отправить уведомления об изменении свойства TotalProgress на этот индикатор выполнения и установить его значение.

Нужно ли мне также перехватывать PropertyChangedEvent в форме?

Изменить: код формы WPF

using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System;
using System.Windows.Threading;

namespace SUpdater
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        BackgroundWorker bw = new BackgroundWorker();
        DownloadFile FileDownloadClass = new DownloadFile();

        public MainWindow()
        {
            InitializeComponent();

            bw.WorkerReportsProgress = true;
            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

            progressBar1.SetBinding(System.Windows.Controls.ProgressBar.ValueProperty, new Binding("TotalPercentCompleted"));
            progressBar1.DataContext = FileDownloadClass;

            FileDownloadClass.PropertyChanged +=new PropertyChangedEventHandler(FileDownloadClass_PropertyChanged);
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            FileDownloadClass.DownloadFiles();

            if ((bw.CancellationPending == true))
                e.Cancel = true;
            else
            {
                bw.ReportProgress(FileDownloadClass.TotalPercentCompleted);
            }

        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                this.lblConnectionStatus.Content = " Download Canceled!";
            }

            else if (!(e.Error == null))
            {
                this.lblConnectionStatus.Content = ("Error: " + e.Error.Message);
            }

            else
            {
                this.lblConnectionStatus.Content = "Done!";
            }
        }

        private void FileDownloadClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {

        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblKbCompleted.Content = e.ProgressPercentage.ToString();

        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            bw.RunWorkerAsync();
        }

    }
}

Изменить: Код класса DownloadFile

    sealed class DownloadFile:INotifyPropertyChanged
    {

        #region Private Fields
            // These fields hold the values for the public properties.
            private int progressBarValue = 0;
            private int totalKbCompleted = 0;
            private int totalBytesReceived = 0;
            private int remoteFileSize = 0;

            private string fileName = String.Empty;
            private string statusMessage = String.Empty;
        #endregion

            public event PropertyChangedEventHandler PropertyChanged;

            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }

            #region Public Properties
            public int TotalKbCompleted
            {
                get { return this.totalKbCompleted; }

                set
                {
                    if (value != this.totalKbCompleted)
                    {
                        this.totalKbCompleted = value/1024;
                        NotifyPropertyChanged("TotalKbCompleted");
                    }
                }                
            }

            public int TotalBytesReceived
            {
                get { return this.totalBytesReceived; }

                set
                {
                    if (value != this.totalBytesReceived)
                    {
                        this.totalBytesReceived = value;
                        NotifyPropertyChanged("TotalBytesReceived");
                    }
                }
            }

            public int RemoteFileSize
            {
                get { return this.remoteFileSize; }

                set
                {
                    if (value != this.remoteFileSize)
                    {
                        this.remoteFileSize = value;
                        NotifyPropertyChanged("RemoteFileSize");
                    }
                }
            }

            public string CurrentFileName
            {
                get { return this.fileName; }

                set
                {
                    if (value != this.fileName)
                    {
                        this.fileName = value;
                        NotifyPropertyChanged("CurrentFileName");
                    }
                }
            }

            public string StatusMessage
            {
                get { return this.statusMessage; }

                set
                {
                    if (value != this.statusMessage)
                    {
                        this.statusMessage = value;
                        NotifyPropertyChanged("StatusMessage");
                    }
                }
            }
            #endregion

        public Int16 DownloadFiles()
        {
            try
            {

                statusMessage = "Attempting Connection with Server";

                DoEvents();
                // create a new ftpclient object with the host and port number to use
                FtpClient ftp = new FtpClient("mySite", 21);

                // registered an event hook for the transfer complete event so we get an update when the transfer is over
                //ftp.TransferComplete += new EventHandler<TransferCompleteEventArgs>(ftp_TransferComplete);

                // open a connection to the ftp server with a username and password
                statusMessage = "Connected. Authenticating ....";
                ftp.Open("User Name", "Password");

                // Determine File Size of the compressed file to download
                statusMessage = "Getting File Details";
                RemoteFileSize = Convert.ToInt32(ftp.GetFileSize("myFile.exe"));

                ftp.TransferProgress += new EventHandler<TransferProgressEventArgs>(ftp_TransferProgress);
                statusMessage = "Download from Server";
                ftp.GetFile("myFile.exe", "E:\\Test\\myFile.exe", FileAction.Create);

                // close the ftp connection
                ftp.Close();
                statusMessage = "Download Complete";
                return 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
                return 0;
            }

        }


        private void ftp_TransferProgress(object sender, TransferProgressEventArgs e)
        {
            totalBytesReceived = Convert.ToInt32(e.BytesTransferred.ToString());
            totalKbCompleted = Convert.ToInt32(totalKbCompleted + Convert.ToInt32(totalBytesReceived));
            progressBarValue = totalKbCompleted;
        }
}

person RKh    schedule 27.07.2011    source источник
comment
Под «Формой» вы имеете в виду Windows Forms?   -  person Jehof    schedule 27.07.2011
comment
Добавьте код DownloadFile, просто добавьте реализацию TotalPercentCompleted и оформление класса   -  person Jalal Said    schedule 27.07.2011
comment
@Jalal: добавьте код класса выше.   -  person RKh    schedule 27.07.2011
comment
@RPK: 1. Имя переменной TotalKbCompleted нет TotalPercentCompleted. поэтому измените строку привязки на: progressBar1.SetBinding(System.Windows.Controls.ProgressBar.ValueProperty, new Binding("TotalKbCompleted")); 2. Вы обновляете totalKbCompleted вместо TotalKbCompleted, поэтому PropertyChanged не сработает.   -  person Jalal Said    schedule 27.07.2011
comment
@Jalal: На самом деле я добавил строку для TotalPercentCompleted позже, и она также обновляется.   -  person RKh    schedule 27.07.2011


Ответы (1)


Вы можете использовать привязку управления:

Формы Windows:

progressBar1.DataBindings.Add("Value", dataSource, dataMember, true,
    DataSourceUpdateMode.OnPropertyChanged);

где dataSource — ваш класс. а dataMember — это имя свойства в этом классе «TotalProgress».

Изменить: для WPF

progressBar1.SetBinding(ProgressBar.ValueProperty, new Binding("ProgressTotal"));
progressBar1.DataContext = the instance of the class you want to bind to its property;

Для получения дополнительной информации о привязке данных wpf см. это и это.

Edit2: вот полный пример:

Foo _foo = new Foo();

DispatcherTimer _dispatcherTimer = new DispatcherTimer();

public MainWindow()
{
    InitializeComponent();

    _dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
    _dispatcherTimer.Tick += _dispatcherTimer_Tick;
    _dispatcherTimer.Start();

    progressBar1.SetBinding(ProgressBar.ValueProperty, new Binding("ProgressTotal"));
    progressBar1.DataContext = _foo;
}

private void _dispatcherTimer_Tick(object sender, EventArgs e)
{
    _foo.ProgressTotal = (_foo.ProgressTotal + 10) % progressBar1.Maximum;
}


public class Foo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private double _progressTotal = 0;

    public double ProgressTotal
    {
        get { return _progressTotal; }
        set 
        {
            if (value != _progressTotal)
            {
                _progressTotal = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("ProgressTotal"));
                }
            }
        }

    }
}

Редактировать. Добавьте таймер для предварительного просмотра эффекта.

Изменить. После загрузки кода проблема появляется в двух местах:

  1. Имя переменной TotalKbCompleted нет TotalPercentCompleted. поэтому измените строку привязки на:

    progressBar1.SetBinding(System.Windows.Controls.ProgressBar.ValueProperty, new Binding("TotalKbCompleted"));
    
  2. Вы обновляете totalKbCompleted вместо TotalKbCompleted, поэтому измененное свойство не сработает.

person Jalal Said    schedule 27.07.2011
comment
Он подчеркивает привязки данных красным цветом. Я добавил ссылку на System.Windows.Data, но все же подчеркнул. В каком NameSpace WPF он находится? - person RKh; 27.07.2011
comment
До сих пор не работает. Что я должен добавить в метод ReportProgress фонового процесса? - person RKh; 27.07.2011
comment
Сделал то же самое, все еще индикатор выполнения не обновляется. Вы можете увидеть мой полный код по этой ссылке. Но я изменил, как вы предложили. stackoverflow .com/questions/6842318/ - person RKh; 27.07.2011
comment
@RPK: Может быть, у вас есть другая проблема в вашем коде. Я проверю. В любом случае, я обновил ответ, добавив таймер для предварительного просмотра эффекта привязки, проверьте его. Однако, чтобы проверить это правильно, создайте новое решение wpf, добавьте к нему индикатор выполнения и вставьте приведенный выше код. - person Jalal Said; 27.07.2011