Привязка 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.