【问题标题】:WPF C# INotifyPropertyChanged doesn't fire upWPF C# INotifyPropertyChanged 没有启动
【发布时间】:2017-05-25 23:41:36
【问题描述】:

我正在构建一个 WPF 应用程序,作为其流程的一部分,它会检查网络连接并在 TextBlock 中显示 IP 地址。

现在,无论出于何种原因,每次 IP 地址发生更改时,我都会尝试更新 TextBlock Text 属性。

我的 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"
                       />

更新 NetWorkStatus.cs -- 静态布尔 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 属性对其进行评估。

为什么当 IP 地址更改时 TextBlock Text 属性没有更新?

【问题讨论】:

  • NotifyIPChanged("IpAddress");应该是 NotifyIPChanged("ipAddress");甚至更好的 NotifyIPChanged(nameOf(ipAddress));或考虑使用 CallerMemberName,然后您根本不必传递名称。
  • 将属性重命名为IpAddress,使其符合广泛接受的命名约定。除此之外,NotifyIPChanged 对于可以为任何属性名称触发 PropertyChanged 事件的方法来说似乎是一个奇怪的名称。此方法的典型名称为 NotifyPropertyChangedRaisePropertyChangedOnPropertyChanged
  • 感谢您的语义建议。我修好了它们。无论如何,应用程序行为不会改变。处理程序没有启动。
  • 绑定也是错误的。应该是Text="{Binding IpAddress}",因为绑定的默认来源已经是当前的DataContext了。
  • 按照克莱门斯的建议做了。还是不行。真的不明白为什么。

标签: wpf binding inotifypropertychanged


【解决方案1】:

将属性重命名为IpAddress,使其符合广泛接受的命名约定。

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

在通知方法的propertyName 参数上使用CallerMemberName 属性,这样您就不必显式地写出名称。

using System.Runtime.CompilerServices;
...

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

正确绑定。当前的DataContext 已经被用作Binding 的源对象。您不得将其添加到属性路径中。

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

在可能的下一步中,您可能希望将视图与视图模型分开并将属性放在单独的类中:

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

    ...
}

并将 Window 的 DataContext 分配给视图模型类的实例:

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

【讨论】:

  • 感谢您的评论。我这样做了。但它不起作用。
  • 从您在问题中显示的内容来看,没有什么可说的了。尝试在IpAdress getter 中放置一个断点,看看它是否被命中。检查NetworkStatus.localIP的值。
  • 这就是问题所在。 IpAddress 在应用程序开始时被调用,但在 IP 更改时不会。但是,检测 IP 更改的事件可以正常工作。这是主要问题。感谢您对克莱门斯的支持。
  • 必须调用 IpAddress 属性的设置器以通知该属性的更改。但是,如果有一些“检测到IP更改的事件”(您的问题中没有显示),它也可以直接调用NotifyPropertyChanged(nameof(IpAddress))
  • 那么您究竟是如何以及从哪里设置 MainWindow 的 ipAddress 属性的呢?
【解决方案2】:

我认为您需要仔细研究 WPF 的工作原理。 作为备注,不需要在后面的代码中实现 INotifyPropertyChanged。如果您正在使用事件,那么您可以自动刷新目标 UI 元素的属性。

但是,在我们的时代,使用代码隐藏并不是一个好习惯。你应该看看 MVVM 模式。你有一个模型、视图和视图模型。 ViewModel 应该实现 INotifyPropertyChanged。

事实上,我认为您的代码是绝对错误的。命名不好:当你实现 INotifyPropertyChanged 时,你不应该只为一个属性实现它,并且名称不应该看起来像:NotifyIPChanged,而应该使用 RaisePropertyChangedNotifyPropertyChangedOnPropertyChanged。在设置器中,您不应刷新其他内容,而应仅刷新您所定位的属性,因为否则会违反 单一责任 原则,就像您的情况一样。还有一个不好的做法是绑定到 Code Behind

我希望这篇文章能让您了解更多关于 MVVM 和 WPF 的信息。祝你好运!

【讨论】:

    【解决方案3】:

    是不是因为IpAdress的第一个字母是Upper,Event没有反应?

    NotifyIPChanged("IpAddress");

    公共字符串 ipAddress
    Text="{Binding DataContext.ipAddress}"

    【讨论】:

    • 那是线程中的一个错字。我在我的代码中正确设置了它。
    猜你喜欢
    • 2011-06-25
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 2014-01-12
    • 2021-08-25
    相关资源
    最近更新 更多