2014-02-17 3 views
2
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ConsoleApplication3 
{ 
    class Cls : INotifyPropertyChanged 
    { 
     private string my; 
     public string MyProperty 
     { 
      get 
      { 
       return my; 
      } 
      set 
      { 
       my = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("MyProperty")); 
      } 

     } 

     public Cls() 
     { 
      MyProperty = "Hello"; 
     } 

     public void print() 
     { 
      Console.WriteLine(MyProperty); 
     } 

     protected virtual void OnPropertyChanged(string name) 
     { 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Cls s = new Cls(); 
      s.print(); 
     } 
    } 
} 

Когда я запускаю этот код, он дает:NullReferenceException когда установлено значение свойства

Необработанное исключение: System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.

Когда я не использую INotifyPropertyChanged, он отлично работает. Я не понимаю причину проблемы.

+2

Какая строка вызывает ошибку? – Kuzgun

+0

'MyProperty =" Hello ";' –

ответ

16

Нет никого, кто прослушивает PropertyChanged, который будет иметь значение null при попытке вызвать его. Используйте OnPropertyChanged метод вместо:

private void OnPropertyChanged(string propertyName){ 
    var handler = PropertyChanged; 
    if (handler != null) 
     handler(this, new PropertyChangedEventArgs(propertyName); 

    // With C# 6 this can be replaced with 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

public string MyProperty 
{ 
    get { return my; } 
    set 
    { 
     if (my == value) 
      return; 

     my = value; 
     OnPropertyChanged("MyProperty"); 
    } 
} 

Чтобы избежать его null вы должны подписаться на него, например, от вашего основного метода:

static void Main(string[] args){ 
    Cls s = new Cls(); 
    s.PropertyChanged += (sender, args) => MessageBox.Show("MyProperty changed!"); 
    s.print(); 
} 

, которая причудливый способ написания

static void Main(string[] args){ 
    Cls s = new Cls(); 
    s.PropertyChanged += ShowMessage; 
    s.print(); 
} 

private void ShowMessage(object sender, PropertyChangedEventArgs args){ 
    MessageBox.Show("MyProperty changed!"); 
} 

Все, что вам более понятно.
Вы можете прочитать больше о событиях here

5

Если ничего не подписались на PropertyChanged событие, выпустив событие выбросит NullReferenceException. Перед запуском события необходимо выполнить нулевую проверку, например:

if (PropertyChanged != null) 
{ 
    PropertyChanged(this, new PropertyChangedEventArgs("MyProperty")); 
} 
+0

Прекрасно работает. Но то, что делает PropertyChanged, не равным null, означает, что в первый раз оно равно null, а после этого оно равно null –

4

У делегата PropertyChanged нет слушателей. Вы всегда должны проверить, что делегат не имеет значения null, прежде чем поднять его.

if (PropertyChanged != null) 
{ 
    PropertyChanged(this, new PropertyChangedEventArgs("MyProperty")); 
} 

Кроме того, судя из вашего кода, вы, вероятно, имел в виду для OnPropertyChanged называться, когда свойство изменяется. Чтобы сделать это, вы должны добавить прослушиватель событий в PropertyChanged и вызвать в слушателе OnPropertyChanged. Вы можете сделать это, добавив следующий код:

//Old ctor 
public Cls() 
{ 
    PropertyChanged += new PropertyChangedEventHandler(Cls_PropertyChanged); //Register the event handler 
    MyProperty = "Hello"; 
} 

void Cls_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    OnPropertyChanged(e.PropertyName); //Call your method 
} 
0

я получил ошибку в моем классе «ViewModel», потому что я опустил INotifyPropertyChanged объявление интерфейса.

так от чего-то вроде этого

public class viewmodel 
    {} 

к этому

public class viewmodel: INotifyPropertyChanged 
{} 

зафиксировал его.


Не было бы полезно для ОП, но надзор, который мог бы сделать кто-то другой?

Смежные вопросы