views:

38

answers:

1

Hello,

I have created a simple MVVM, with only three classes CashFlowView, CashFlowViewModel, CashFlowModel.

I use an infragistic's 9.1 XamDataPresenter (or xamDataGrid).

    <igDP:XamDataPresenter Name="xamDataPresenter1" DataSource="{Binding Source={StaticResource CashFlowData}}">

    <ObjectDataProvider x:Key="CashFlowData" ObjectType="{x:Type ViewModel:CashflowViewModel}" MethodName="GetCashFlows" />

Inside my ViewModel:

public ObservableCollection<CashflowModel> GetCashFlows()
        {
            return new ObservableCollection<CashflowModel>() { ... };
        }

ViewModel is connected to View by this:

this.DataContext = new CashflowViewModel();

As long as I connect the grid to the ObjectDataProvider its perfectly running fine. But I wished I could just connect to a property within my ViewModel instead.

According to Infragistics all I have to do is this:

<igDP:XamDataGrid DataSource="{Binding Path=ViewModelCollection}"/>

But in this case it seems I need to bind to a collection of another ViewModel to represent my rows inside the grid. And thats where I get confused.

I tried this and it doesnt work:

<igDP:XamDataPresenter Name="xamDataPresenter1" DataSource="{Binding Path=CashFlows}">

Inside the ViewModel:

public ObservableCollection<CashflowDataGridViewModel> CashFlows
        {
            get
            {
                return new ObservableCollection<CashflowDataGridViewModel>();
            }
        }

But how do I create my second ViewModel (CashflowDataGridViewModel) ?

I tried adding this proprty within this second ViewModel:

public CashflowModel CashFlow
        {
            get
            {
                return new CashflowModel() {...};
            }
        }

But all I get shown on my view is "Cashflow" column header without any of the underlying headers of the actual cashflowModel class.

Please help, am badly stuck ;)

+1  A: 

To be able to bind the View to properties on the ViewModel, the DataContext needs to be set to an instance of your ViewModel. What I commonly do is to include the following line in the constructor of the code-behind for my View:

this.DataContext = new SomeAwesomeViewModel();

You can also set the DataContext for containers if you want different groups of controls to use different ViewModels (e.g., Grid.DataContext, StackPanel.DataContext, etc.).

Once you have the DataContext set, you should be able to bind to the properties of that ViewModel.

Update

Here's a bit of sample code to get you going.

public class CashFlowViewModel
{
    public ObservableCollection<FlowViewModel> DataGridData
    {
        get...
    }
}

That's the property which should provide the data for the DataGrid. Now, here's what the FlowViewModel class could look like.

public class FlowViewModel
{
    decimal flowAmount;
    public decimal FlowAmount
    {
        get { return flowAmount; }
        set
        {
            if(flowAmount == value)
                return;

            flowAmount = value;
            NotifyPropertyChanged("FlowAmount");
        }
    }
    .
    .
    .

    private void NotifyPropertyChanged(string propertyName)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Eric
Hi Eric, it is already connected like this: this.DataContext = new CashflowViewModel(); I have one property inside the second ViewModel (CashflowDataGridViewModel), and I can see that Property. But not the actual content of the CashflowModel for each row. Maybe I need screenshots to clarify this...
Kave
I just re-read your question, and I think I know what you're asking.Your CashFlowViewModel needs to expose an ObservableCollection<FlowViewModel> where a FlowViewModel represents the data which will be contained in one row of the DataGrid? Is that correct?If so, then, creating the FlowViewModel should be pretty simple. Create a new class that implements the INotifyPropertyChanged interface. Create properties for each entry in the row, and make sure that changes trigger a PropertyChanged event.
Eric
Thankkkk you, its working! :) Now I understand. Its tempting to just add the Notifications to the model itself. But I think thats a mistake, since we would polute the model with interface stuff such as INotifyPropertyChanged. Hence its better to have a second ViewModel that wraps the model and adds the INotifyPropertyChanged capabilities in there. Is my assumption correct?
Kave
Good! Glad it's working. Yes, you're correct; the model should just be concerned with what it's...modeling. It shouldn't care about what it needs to implement to show a view. That's the job of the ViewModel. So, the separation of concerns is thus, (1) The View just shows data and allows interaction. It receives the data via data-binding. (2) The model contains the data to be manipulated. (3) The ViewModel is concerned with taking the data from the Model and presenting it to the View.
Eric