Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么WPF支持绑定到对象的属性,而不支持绑定到字段?_.net_Wpf_Binding_Field - Fatal编程技术网

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

.net 为什么WPF支持绑定到对象的属性,而不支持绑定到字段?,.net,wpf,binding,field,.net,Wpf,Binding,Field,我有一个WCF服务,它通过如下结构传递状态更新: [DataContract] public struct StatusInfo { [DataMember] public int Total; [DataMember] public string Authority; } ... public StatusInfo GetStatus() { ... } 我在ViewModel中公开一个属性,如下所示: public class ServiceViewModel : View

我有一个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绑定的内容?您可以绑定到字段还是属性绑定是唯一的方法?

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

出于我无法解释的原因,公共领域是个坏主意。它们应该是属性,事实。同样,可变结构也是一个非常糟糕的主意。不仅如此,它还可以防止意外的数据丢失(通常与可变结构相关)。这应该是一个类:

[DataContract]
public class StatusInfo
{
    [DataMember] public int Total {get;set;}
    [DataMember] public string Authority {get;set;}
}
它现在将按您认为的方式运行。如果希望它是一个不可变的结构,那就可以了(当然,数据绑定是单向的):

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


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

如果这是对我问题的回答,那么它在很多方面都是错误的。首先,通常(首先)在堆栈上分配作为变量的值类型。如果将它们推送到堆上(例如在数组/列表中),则开销与类没有多大区别——一小段对象头加上一个引用。结构应该总是。具有多个字段的内容将过大,可能会破坏堆栈,也可能会由于临时设置而导致延迟。此外,结构应该是不可变的-除非你真的知道你在做什么

几乎任何表示对象的东西都应该是不可修改的

如果要访问数据库,与进程外(可能是通过网络)相比,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();
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
结构MyStruct
{
公共int Id;
公共字符串名称;
公共日期出生日期;
公共字符串评论;
}
类MyClass
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共日期时间出生日期{get;set;}
公共字符串注释{get;set;}
}
静态类程序
{
静态void Main()
{
DateTime dob=DateTime.Today;
const int SIZE=1000000;
秒表=Stopwatch.StartNew();
列表s=新列表(大小);
对于(int i=0;i
我只能猜测他们为什么只支持属性:可能是因为在.NET framework中似乎有一个普遍的约定,即永远不公开可变字段(),而且他们不知何故希望所有程序员都遵循相同的约定


同样,虽然字段和属性以相同的语法访问,但数据绑定使用反射,并且(我听说)反射必须不同于访问字段而不是访问属性。< /P>作为C++程序员,我很难找到您的评论。我似乎也得出了不同的结论。例如,你说,“大约慢了5倍,但仍然非常非常快。”而我认为,“结构的使用大约快了5倍,但仍然非常非常慢。”@Daniel sigh,我们再来一遍,“C++比任何东西都快,而且必须一直使用”(sigh)。在各种各样的应用中,没有什么区别,除了一个更容易得到正确的。我从来没有说过C++更快。得出这样的结论表明你有一些严重的先入之见(或者可能是误解)。“在各种各样的应用中,除了一个明显的更容易得到正确的区别之外,没有明显的区别”——所以我们同意,尽管C++可能更快,但这并不重要——但是,C++使它更容易得到正确的结果,这是很重要的。或者我只是误解了你的话来支持我的论点。。。叹息:“丹尼尔,也许我误解了你的意思,”作为一个C++

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();
    }
}