2017-01-11 5 views
0

Я создаю приложение WPF, которое как часть потока, проверяет сетевое подключение и отображает IP-адрес в TextBlock.WPF C# INotifyPropertyChanged не запускается

Теперь я пытаюсь обновить свойство TextBlock Text каждый раз, когда IP-адрес изменяется по какой-либо причине.

У меня есть изменение IP-адреса, работающее нормально, но я не мог заставить INotifyPropertyChanged работать.

Я прочитал все возможные решения и реализации, но не смог найти рабочий код.

Публичное свойство получает значение из статической строки из класса Network Helper. Таким образом, код:

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

     public MainWindow() 
    { 
     InitializeComponent(); 

     DataContext = this; 
    } 

     public string ipAddress 
    { 
     get { return NetworkStatus.localIP; } 
     set 
     { 
      if (value != NetworkStatus.localIP) 
      { 
       NetworkStatus.localIP = value; 

       NotifyIPChanged("IpAddress"); 
      } 
     } 
    } 
    private void NotifyIPChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 

XAML:

<TextBlock x:Name="ipTxt"        
         TextWrapping="Wrap" 
         HorizontalAlignment="Left" 
         VerticalAlignment="Center" 
         Text="{Binding DataContext.ipAddress}" 
         Height="30" 
         Width="110" 
         Margin="-30,10,0,-10" 
         /> 

UPDATE NetWorkStatus.cs - статические BOOL IsNetworkAvailable() ...

      if (statistics.BytesReceived > 0 || statistics.BytesSent > 0) 
         { 
          IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName()); 
          localIP = host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString(); 
          return true; 
         } 

Как вы можете см. этот метод устанавливает статическую строку «localIP». Затем это оценивается с помощью свойства IpAddress.

Почему свойство TextBlock Text не обновляется при изменении IP-адреса?

+0

NotifyIPChanged ("IpAddress"); должен быть NotifyIPChanged ("ipAddress"); или даже лучше NotifyIPChanged (nameOf (ipAddress)); или подумайте о том, как использовать CallerMemberName, а затем вам вообще не нужно передавать имя. – adminSoftDK

+0

Переименуйте свойство в 'IpAddress', чтобы оно соответствовало общепринятым соглашениям об именах. Кроме того, 'NotifyIPChanged' представляется нечетным именем для метода, который может запускать событие PropertyChanged для любого имени свойства. Типичными именами для этого метода являются «NotifyPropertyChanged», «RaisePropertyChanged» или «OnPropertyChanged». – Clemens

+0

Благодарим вас за семантические предложения. Я исправил их. В любом случае поведение приложения не изменяется. Обработчик не запускается. – user1776401

ответ

-1

Возможно ли, что событие не реагирует, потому что первая буква IpAdress является верхней?

NotifyIPChanged ("я Paddress");

общественная строка Ipaddress
Text = "{Binding DataContext. я Paddress}"

+0

Это была опечатка в потоке. Я правильно ее установил в своем коде. – user1776401

0

Я думаю, вам нужно присмотреться к тому, как WPF работ. В качестве примечания, нет необходимости в реализации INotifyPropertyChanged в коде позади. Если вы используете события, вы можете автоматически обновлять свойства целевого элемента пользовательского интерфейса.

Однако использование кода позади не является хорошей практикой в ​​наши дни. Вы должны взглянуть на шаблон MVVM. У вас есть Model, View и ViewModel. ViewModel должен реализовать INotifyPropertyChanged.

Дело в том, что ваш код, на мой взгляд, абсолютно неправильный. Именование не в порядке: при реализации INotifyPropertyChanged вы не должны реализовать только собственность, и имя не должно выглядеть так: NotifyIPChanged, вместо этого вы должны использовать RaisePropertyChanged, NotifyPropertyChanged или OnPropertyChanged. В сеттерах вы не должны обновлять что-то еще, а только свойство, на которое вы нацеливаетесь, потому что в противном случае нарушается принцип Single Responsability, как в вашем случае.Также плохой практикой является привязка к Код за.

Надеюсь, этот пост заставит вас больше узнать о MVVM и WPF. Удачи!

1

Переименуйте свойство в IpAddress, чтобы оно соответствовало общепринятым соглашениям об именах.

public string IpAddress 
{ 
    get { return NetworkStatus.localIP; } 
    set 
    { 
     if (value != NetworkStatus.localIP) 
     { 
      NetworkStatus.localIP = value; 
      NotifyPropertyChanged(); 
     } 
    } 

Используйте атрибут CallerMemberName от параметра вашего метода уведомления propertyName, так что вам не нужно писать имя явно.

using System.Runtime.CompilerServices; 
... 

private void NotifyPropertyChanged([CallerMemberName] string propertyName = null) 
{ 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

Привяжите его правильно. Текущий DataContext уже используется как исходный объект привязки. Вы не должны добавлять его в путь свойств.

<TextBlock Text="{Binding IpAddress}" ... /> 

В возможном следующем шаге вы можете отделить представление от модели представления и поставить свойство в отдельном классе:

public class ViewModel : INotifyPropertyChanged 
{ 
    public string IpAddress 
    { 
     get ... 
     set ... 
    } 

    ... 
} 

и назначить окна DataContext к экземпляру вида модели:

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = new ViewModel(); 
} 
+0

Спасибо за ваши замечания. Я это сделал. Но он не работает. – user1776401

+0

От того, что вы показали в своем вопросе, говорить нечего. Попытайтесь положить контрольную точку в геттер «IpAdress», чтобы узнать, попадает ли он. Проверьте значение 'NetworkStatus.localIP'. – Clemens

+0

В этом проблема. IpAddress вызывается в начале приложения, но это не происходит при изменении IP-адреса. Однако событие, которое обнаруживает изменение IP, работает правильно. Это главный вопрос. Спасибо за вашу поддержку Клеменса. – user1776401