Привязка WPF Grid к модели

У меня есть приложение MVVM, которое имеет сетку WPF, которая содержит другие встроенные сетки WPF, и в то же время каждое из них содержит несколько полей (WPF TextBlocks).

Очень упрощенный пример - Просмотр:

<Grid>

   <Grid>
       // Row definitions
       // Colum definitions
       <TextBlock Grid.Row="3" Grid.Column="0"
                  Text="{Binding Path=SomeField1}" /> 
   <Grid>

   <Grid>
       // Row definitions
       // Colum definitions
       <TextBlock Grid.Row="0" Grid.Column="1"
                  Text="{Binding Path=SomeField2}" /> 
   <Grid>

</Grid>

Каждый из этих TextBlocks привязан к строковым свойствам, определенным в модели представления.

Модель представления (реализует INotifyPropertyChanged):

private string _someField1;
public string SomeField1
{
   get return _someField1;
   set 
   {
       if (_someField1 == value) return;
       _someField1 = value;
       OnPropertyChanged("SomeField1");
   }
}

private string _someField2;
public string SomeField2
{
   get return _someField2;
   set 
   {
       if (_someField2 == value) return;
       _someField2 = value;
       OnPropertyChanged("SomeField2");
   }
}

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

Модель:

public class MyModel
{
    private string _someField1;
    public string SomeField1
    {
       get return _someField1;
       set 
       {
           if (_someField1 == value) return;
           _someField1 = value;
       }
    }

    private string _someField2;
    public string SomeField2
    {
       get return _someField2;
       set 
       {
           if (_someField2 == value) return;
           _someField2 = value;
       }
    }
}

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

Просмотреть метод модели, который извлекает полученные данные:

private void DataReceived(MyModel data)
{
    this.SomeField1= data.SomeField1;
    this.SomeField2= data.SomeField2;
}

Проблема заключается в том, что мне нужно дважды определить свойства, с точки зрения модели и модели. Поэтому я хочу избежать этого, я хотел бы привязать Textblocks непосредственно к свойствам в модели, а не определять свойства в модели представления, чтобы избежать избыточного кода. Или, например, есть ли какой-нибудь простой способ привязать мою модель (MyModel) к внешней основной сетке, а затем к текстовым полям, привязанным к свойствам в модели представления (аналогично при привязке источника элементов в сетке данных)?

2 ответа

Я бы предложил модель общего вида:

public class BaseViewModel<TModel>
{
    public TModel Model
    {
        get;
        private set;
    }

    public BaseViewModel(TModel model)
    {
        this.Model = model;
    }
}

Тогда вы можете привязать к нему:

<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding Path=Model.SomeField1}" />

Я думал, если ниже это нормально и уважает образец MVVM. Я подумал, увидев решение, предложенное c0d3b34n. Я думаю, что это проще и не нужно делать интерфейсы и модель общего вида. Я проверил, и это работает:

Объявите свойство в виде модели:

private MyModel _model;
public MyModel Model
{
    get { return _model; }
    set   
    {
         _model = value;
         OnPropertyChanged("Model");
    }
}

Тогда в представлении:

<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding Path=Model.SomeField1}" />

... и то же самое для остальной части TextBlocks.

В заключение:

 private void DataReceived(MyModel data)
 {
       this.Model = data;
 }

Но, как сказал BionicCode в комментариях, это решение нарушает схему MVVM.

Другие вопросы по тегам