2009-05-09 3 views
16

У меня есть службы WCF, которая проходит вокруг обновления статуса через структуру, как так:Почему WPF поддерживает привязку к свойствам объекта, но не полям?

[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? Можете ли вы привязываться к полю или связывать свойство единственным способом?

ответ

21

Переплет Обычно не работает в полях. Большинство привязок основаны, в частности, на модели 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; 
    } 
} 

Однако, я бы первый вопрос, почему это структура в первую очередь. Это очень редкий, чтобы написать структуру на языках .NET. Имейте в виду, что прокси-сервер WCF «mex» будет создавать его как класс у потребителя в любом случае (если вы не используете совместное использование сборок).


В ответ на «почему использовать структуры» ответ («неизвестный (Google)»):

Если это ответ на мой вопрос, это неправильно во многих отношениях. Во-первых, типы значений как переменные обычно выделяются (сначала) в стеке. Если они попадают в кучу (например, в массиве/списке), нет большой разницы в накладных расходах от класса - небольшой бит заголовка объекта плюс ссылка. Структуры всегда должны быть small. Что-то с несколькими полями будет чрезмерно крупным и будет либо убивать ваш стек, либо просто вызвать медленность из-за блуждания. Кроме того, структуры должны быть неизменными - если вы не действительно знаете, что вы делаете.

Практически все, что представляет объект, должно быть бескомпромиссным.

Если вы попадаете в базу данных, скорость 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(); 
    } 
} 
+4

Как программист на C++ я нахожу, что ваши комментарии выше очень трудно понять. Я также, похоже, прихожу к разным выводам. Например, вы говорите: «Итак, примерно в 5 раз медленнее, но все же очень, очень быстро». В то время как я вижу это как: «Использование структур в 5 раз быстрее, но все же очень, очень медленно». –

+7

@ Даниэль вздыхает, здесь мы снова говорим: «C++ быстрее, чем все, когда-либо, и должен использоваться всегда» (вздох). В широком спектре применений нет заметной разницы, кроме одного, что значительно легче получить право. –

+0

Я никогда не говорил, что C++ был быстрее! Заключая такие, вы указали, что у вас есть серьезные предубеждения (или, может быть, неправильные представления). «В самых разных приложениях нет заметной разницы, кроме одного, что значительно легче получить право» - поэтому мы согласны, хотя C++ может быть быстрее, это не важно - однако C++ упрощает правильное и правильное это важно. Или, может быть, я просто неправильно истолковал то, что вы сказали, чтобы поддержать мой аргумент ... В самом деле. –

0

Я могу только догадываться, почему они поддерживают только свойства: возможно, потому, что, как представляется, универсальная конвенция в рамках .NET никогда не подвергать изменяемых полей (probably to safeguard binary compatibility), и они как-то ожидается, все программисты следовать тем же условность.

Кроме того, хотя поля и свойства доступны с одним и тем же синтаксисом, привязка данных использует отражение, и (так что я слышал) отражение должно использоваться по-разному для доступа к полям, чем для доступа к свойствам.

 Смежные вопросы

  • Нет связанных вопросов^_^