8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

为什么 WPF 支持绑定到对象的属性,但不支持字段?

Ryan Day 2月前

34 0

我有一个 WCF 服务,它通过如下结构传递状态更新:[DataContract]public struct StatusInfo{ [DataMember] public int Total; [DataMember] public string Authority...

我有一个 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 无法处理字段的单向绑定很奇怪。从语法上讲,您可以在代码中以相同的方式访问它们,并且仅为 StatusInfo 结构创建自定义视图模型似乎很愚蠢。我是否遗漏了有关 WPF 绑定的某些内容?您可以绑定到字段吗?还是属性绑定是唯一的方法?

帖子版权声明 1、本帖标题:为什么 WPF 支持绑定到对象的属性,但不支持字段?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Ryan Day在本站《xaml》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 绑定 通常 不适用于字段。大多数绑定部分基于 ComponentModel PropertyDescriptor 模型,该模型(默认情况下)适用于属性。这会启用通知、验证等(这些都不适用于字段)。

    由于很多原因,我无法一一列举,公共字段不是一个好主意。事实上,它们应该是属性。同样,可变结构体也是一个糟糕的主意。最重要的是,它可以防止意外的数据丢失(通常与可变结构体有关)。这应该是一个类:

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

    现在它的行为将如您所想的那样。如果您希望它是一个 不可变 结构,那也没问题(但数据绑定当然只能是单向的):

    [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;
        }
    }
    

    但是,我首先要问的是,这为什么是一个结构。 非常罕见 。请记住,WCF \'mex\' 代理层无论如何都会在消费者处将其创建为类(除非您使用程序集共享)。


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

    如果这是对我的问题的回答,那么它在很多方面都是错误的。首先,值类型 作为变量 通常首先在堆栈上分配。如果将它们推送到堆上(例如在数组/列表中),则与类相比,开销没有太大区别 - 一小段对象头加上一个引用。结构应该总是 很小 。具有多个字段的东西会过大,并且会毁掉你的堆栈或只是由于位图传输而导致速度变慢。此外,结构应该是不可变的 - 除非你 真的 知道自己在做什么。

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

    如果您正在访问数据库,与进程外和可能通过网络相比,结构与类的速度不是问题。即使速度慢一点,与正确处理相比也没什么意义 - 即将对象视为对象。

    一些指标如下 个 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();
        }
    }
    
  • flow 2月前 0 只看Ta
    引用 3

    作为一名 C++ 程序员,我发现你上面的评论很难理解。我似乎也得出了不同的结论。例如,你说,“所以速度慢了 5 倍,但仍然非常非常快。”而我认为,“使用结构的速度大约快 5 倍,但仍然非常非常慢。”

  • @Daniel 叹息,我们又来了,“C++ 比任何东西都快,永远如此,必须一直使用”(叹息)。在各种各样的应用程序中,没有明显的区别,除了一个应用程序更容易正确使用之外。

  • 我从未说过 C++ 更快!得出这样的结论表明你有一些严重的先入之见(或可能是误解)。\'在各种各样的应用程序中,没有明显的区别,除了一个更容易正确\' - 所以我们同意,虽然 C++ 可能更快,但这并不重要 - 但是,C++ 更容易正确,这是很重要的。或者也许我只是误解了你所说的话来支持我的论点...... 真是叹息。

  • @Daniel 也许我误解了你的“作为一名 C++ 程序员......但仍然非常非常慢”的意思

  • 您的性能测试可能太短,无法正确测量 GC 开销。尝试修改您的测试:pastebin.com/Ajkj0hdm - 现在类的速度慢了 12 倍,因为 80% 的时间都花在了 GC 上。现在将 SIZE 调高到 10M,并观察 \'private bytes\':结构为 200 MB,类为 1 GB。

  • 我只能猜测为什么他们只支持属性:也许是因为在 .NET 框架中似乎有一个通用约定,即永不公开可变字段( 可能是为了维护二进制兼容性 ),并且他们不知何故希望所有程序员都遵循相同的约定。

    此外,尽管使用相同的语法访问字段和属性,但数据绑定使用反射,并且(据我所知)访问字段和访问属性时反射的使用方式必须不同。

返回
作者最近主题: