.net - 为什么 WPF 支持绑定(bind)到对象的属性,但不支持绑定(bind)字段?

标签 .net wpf binding field

我有一个 WCF 服务,它通过如下结构传递状态更新:

[DataContract]
public struct StatusInfo
{
    [DataMember] public int Total;
    [DataMember] public string Authority;
}
...
public StatusInfo GetStatus() { ... }

我在 ViewModel 中公开一个属性,如下所示:
public class ServiceViewModel : ViewModel
{
    public StatusInfo CurrentStatus
    {
        get{ return _currentStatus; }
        set
        { 
            _currentStatus = value;
            OnPropertyChanged( () => CurrentStatus );
        }
    }    
}

XAML 就像这样:
<TextBox Text="{Binding CurrentStatus.Total}" />

当我运行该应用程序时,我在输出窗口中看到错误,表明找不到 Total 属性。我检查并仔细检查并正确输入。我突然想到这些错误特别表明找不到“属性”。因此,向结构添加属性使其工作正常。但这对我来说似乎很奇怪,WPF 无法处理与字段的单向绑定(bind)。从语法上讲,您在代码中以相同的方式访问它们,并且只为 StatusInfo 结构创建自定义 View 模型似乎很愚蠢。我是否错过了有关 WPF 绑定(bind)的内容?您可以绑定(bind)到字段还是属性绑定(bind)是唯一的方法?

最佳答案

绑定(bind)通常不适用于字段。大多数绑定(bind)部分基于 ComponentModel PropertyDescriptor模型,(默认情况下)适用于属性。这将启用通知、验证等(这些都不适用于字段)。

由于我无法解释的更多原因,公共(public)领域是一个坏主意。它们应该是属性,事实。同样,可变结构是 非常馊主意。尤其重要的是,它可以防止意外的数据丢失(通常与可变结构相关联)。这应该是一个类:

[DataContract]
public class StatusInfo
{
    [DataMember] public int Total {get;set;}
    [DataMember] public string Authority {get;set;}
}

它现在将按照您认为的方式运行。如果您希望它是 不可变 struct,那没关系(但数据绑定(bind)当然是单向的):
[DataContract]
public struct StatusInfo
{
    [DataMember] public int Total {get;private set;}
    [DataMember] public string Authority {get;private set;}

    public StatusInfo(int total, string authority) : this() {
        Total = total;
        Authority = authority;
    }
}

但是,我首先会质疑为什么这是一个结构。是非常罕见用 .NET 语言编写结构。请记住,WCF“mex”代理层无论如何都会在消费者处将其创建为一个类(除非您使用程序集共享)。

回答“为什么使用结构”回复(“未知(谷歌)”):

如果这是对我问题的回答,那么它在很多方面都是错误的。首先,作为变量的值类型通常(首先)分配在堆栈上。如果它们被推送到堆上(例如在数组/列表中),那么与类的开销没有太大区别——一小部分对象头加上一个引用。结构应始终为 .具有多个字段的东西会过大,并且会破坏您的堆栈或由于 blitting 而导致缓慢。此外,结构应该是不可变的——除非你 真的知道你在做什么。

几乎任何代表对象的东西都应该是不可变的。

如果您正在访问数据库,那么与进程外并且可能通过网络相比,struct vs class 的速度不是问题。即使它有点慢,与正确处理相比毫无意义 - 即将对象视为对象。

作为超过 的一些指标1M 对象:
struct/field: 50ms
class/property: 229ms

基于以下内容(速度差异在于对象分配,而不是字段与属性)。所以大约慢了 5 倍,但仍然 非常非常快 .由于这不会成为您的瓶颈,因此不要过早地优化它!
using System;
using System.Collections.Generic;
using System.Diagnostics;
struct MyStruct
{
    public int Id;
    public string Name;
    public DateTime DateOfBirth;
    public string Comment;
}
class MyClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Comment { get; set; }
}
static class Program
{
    static void Main()
    {
        DateTime dob = DateTime.Today;
        const int SIZE = 1000000;
        Stopwatch watch = Stopwatch.StartNew();
        List<MyStruct> s = new List<MyStruct>(SIZE);
        for (int i = 0; i < SIZE; i++)
        {
            s.Add(new MyStruct { Comment = "abc", DateOfBirth = dob,
                     Id = 123, Name = "def" });
        }
        watch.Stop();
        Console.WriteLine("struct/field: "
                  + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        List<MyClass> c = new List<MyClass>(SIZE);
        for (int i = 0; i < SIZE; i++)
        {
            c.Add(new MyClass { Comment = "abc", DateOfBirth = dob,
                     Id = 123, Name = "def" });
        }
        watch.Stop();
        Console.WriteLine("class/property: "
                   + watch.ElapsedMilliseconds + "ms");
        Console.ReadLine();
    }
}

关于.net - 为什么 WPF 支持绑定(bind)到对象的属性,但不支持绑定(bind)字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56916525/

相关文章:

wpf - MVVM 主窗口控件从子用户控件绑定(bind)

c# - 您可以通过 TcpClient 发送大于 SendBufferSize 的文件吗?

c# - Windows 10 上的 .NET FontFamily 内存泄漏

c# - 自定义DXGrid的 header (DevExpress wpf网格控件)

wpf - 列表框中的 self 工具提示

c# - 带有单点触控的 Facebook api

javascript - Angularjs - ng-if - 绕过/解决范围逻辑

.net - 我可以将 Azure 移动服务与 Unity 3d 结合使用吗?

c# - Entity Framework - 批量更新/插入/删除缓慢

c# - WPF中的Web浏览器控件