2013-07-18 4 views
2

Отсутствие вопросов по этому вопросу может быть признаком запаха кода здесь, но ... Можно ли написать метод расширения для класса и привязки к ним, как будто бы вы обладаете свойством?Возможно ли связать привязку к методу расширения?

Предполагается, что мне предоставляется структура классов, которую я не могу кардинально изменить, но я хочу выразить серию своих логических свойств в виде строки для целей отображения.

упрощенный базовый класс:

public class Transmission 
{ 
    public int ID { get; set; } 
    public bool Cancelled { get; set; } 
    public bool Stored { get; set; } 
    public bool Recorded { get; set; } 
} 

Мой метод расширения:

public static class Extensions 
{ 
    public static string Status(this Transmission trans) 
    { 
     StringBuilder sb = new StringBuilder("|"); 
     if (trans.Cancelled) 
      sb.Append("| Cancelled "); 
     if (trans.Recorded) 
      sb.Append("| Recorded "); 
     if (trans.Stored) 
      sb.Append("| Stored "); 
     sb.Append("||"); 

     return sb.ToString(); 
    } 
} 

Чтобы добавить дополнительную сложность, я передается список этих вещей, и я пытаюсь связать с datagrid (с сильно ограниченным опытом XAML).

<GroupBox Header="Here is an amazing list of results for you to violate horribly."> 
    <DataGrid ItemsSource="{Binding Transmissions, Mode=OneWay}" AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Width="*" Header="Local ID" Binding="{Binding ID, Mode=OneWay}"/> 
      <DataGridTextColumn Width="*" Header="Status" Binding="{Binding Status, Mode=OneWay}"/> 
     </DataGrid.Columns> 
    </DataGrid> 
</GroupBox> 

Я проверил код и смог без проблем связаться с ID. Однако «Статус» вообще не подбирается. Есть ли уловка для привязки к свойству расширения? Или было бы более разумным просто написать класс декоратора/фасада и связать это с этим?

+2

Вы не можете привязываться к методу расширения ... на самом деле вы не можете привязываться к какому-либо методу, должно быть свойство ... – McGarnagle

+1

Также нет такой вещи, как «свойство расширения» –

+2

@MarcGravell: К сожалению ... –

ответ

2

Когда вы прошли список передачи объектов вы можете использовать шаблон Façade и хранить их в контейнере разработан ...

public class TransmissionContainer : INotifyPropertyChanged 
{ 
    private readonly Transmission _transmission; 
    public TransmissionContainer(Transmission transmission) 
    { 
     _transmission = transmission; 
    } 
    private int _id; 
    public int Id 
    { 
     [DebuggerStepThrough] 
     get { return _transmission.ID; } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != _transmission.ID) 
      { 
       _transmission.ID = value; 
       OnPropertyChanged("Id"); 
      } 
     } 
    } 
    public bool Cancelled 
    { 
     [DebuggerStepThrough] 
     get { return _transmission.Cancelled } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != _transmission.Cancelled) 
      { 
       _transmission.Cancelled = value; 
       OnPropertyChanged("Cancelled"); 
       OnPropertyChanged("Status"); 
      } 
     } 
    } 
    public string Status 
    { 
     [DebuggerStepThrough] 
     get 
     { 
      StringBuilder sb = new StringBuilder("|"); 
      if (_transmission.Cancelled) 
       sb.Append("| Cancelled "); 
      if (_transmission.Recorded) 
       sb.Append("| Recorded "); 
      if (_transmission.Stored) 
       sb.Append("| Stored "); 
      sb.Append("||"); 
      return sb.ToString(); 
     } 
    } 
    // 
    // code in other properties here 
    // 
    #region INotifyPropertyChanged Implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected virtual void OnPropertyChanged(string name) 
    { 
     var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null); 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
} 

Это класс контейнер, который создает фасад, к которому ваш Xaml может связывать прозрачно. Как показано, каждый из выставленных свойств просто отсылает обратно значение в частном экземпляре Передачи. Изменения передаются в механизм привязки WPF через интерфейс INotifyPropertyChanged.

Чтобы создать экземпляр, вы можете создать его с исходным классом передачи. Чтобы связать коллекцию этих контейнеров, вы можете объявить ObservableCollection типа TransmissionContainer. Это означает, что список связан в дополнение к различным изменениям свойств.

В этом подходе ваше свойство 'extension' является еще одним открытым свойством, которое не имеет сеттера. Обратите внимание, что изменения других участников, которые влияют на статус, вызывают уведомление от имени свойства 'extension'. Кодирование в остальных членах класса передачи должно занимать около 20 минут ...

+0

Благодарим вас за подробное описание этого процесса! Я дам ему шанс и отметьте это как ответ, если все сработает. – MadHenchbot

+1

Он будет работать, учитывая, как вы описали проблему. Ваш вопрос - это чистое фасадное решение, а у фасадного рисунка - выдающаяся родословная. :) –

5

Это то, что вы обычно используете шаблон, такой как MVVM для. Вы добавляете свойства к модели , которые основаны на модели и имеют отношение только к виду. Модель представления может содержать ссылку на модель либо напрямую привязываться к ее свойствам, либо отображать их на модели представления (для развязки я бы выбрал последнюю).

+0

Это действительно мой первый проект с MVVM, так что это может быть глупый вопрос, но ... Каким будет лучший способ отразить мою * коллекцию объектов? Создать новый класс контейнера на основе исходной модели передачи? Будет ли это похоже на ответ Гарри Васса на эту тему? – MadHenchbot

+0

@MadHenchbot: Ваша коллекция будет содержать модели вида (класс контейнера), и каждая модель представления содержит свою модель. Это действительно было бы похоже на то, что опубликовал Vass, он также прекрасно отмечает, как вам нужно будет сменить уведомление об изменении. Кроме того, не называйте их * нитями *, это оскорбление, самая сильная точка SO, которую мы делаем * not *, с потоками. –

+0

Точка снята. :) Спасибо за разъяснения! – MadHenchbot