简体   繁体   中英

Binding WPF Grid to a model

I have a MVVM application which has a WPF Grid which contains other embedded WPF Grids and at the same time, each of them contain some fields (WPF TextBlocks).

Very simplified example - View:

<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>

Each of these TextBlocks are bound to a string properties defined in view model.

View model (It implements 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");
   }
}

Then I have a model, I mean, a class with some public properties that is filled in by one process once data is obtained from a device. This class contains exactly the same properties as those defined in the view model.

Model :

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

Later from view model I extract the data from this class (model), and I assign the values of those properties to the matching properties in view model. Finally, since view is bound to these properties, then view is correctly updated with values as below example.

View model method which extracts data received :

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

The problem is that I have to define twice the properties, in view model and model. So I want to avoid this, I would like to bind Textblocks directly to properties in model and not defined the properties in view model to avoid redundant code. Or for example, is there any easy way to bind my model (MyModel) to the outer main grid and then textboxes bound to the properties in the view model (similar when bound itemsource in datagrid)?

I would suggest a generic view model:

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

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

Then you can bind to it:

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

I was thinking if below it is ok and respects MVVM pattern. I have thought it after seeing solution proposed by c0d3b34n. I think it is simpler and no need to do interfaces and generic view model. I have checked and it works:

Declare a property in view model:

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

Then in the view:

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

... and the same for the rest of TextBlocks.

Finally:

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

But as said by BionicCode in comments, this solution breaks MVVM pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM