Paul Gibson
Paul Gibson

Reputation: 634

How to get my ViewModel instantiated

I have an application that works, and now I'm trying to do it with proper MVVM. As I understand it from many months of reading, the LinqToSQL classes (by VS2013) are my model, as is the SQL Server database that it uses. The UI is the view, and I am implementing some ObservableCollections as my view model. So here is the ViewModel:

    partial class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    static DataClasses1DataContext _dataDc = new DataClasses1DataContext();
    ObservableDocuments _oDoc = new ObservableDocuments(_dataDc);

    public ObservableCollection<Document> oDoc
    {
        get
        {
            return _oDoc;
        }
    }

    public ICommand LoadData
    {
        get;
        private set;
    }

    protected void RaisePropertyChangedEvent(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

In the working version, the DataContext and ObservableDocuments lines were in the MainWindow code . . . so I have moved them. Here is the xaml:

<Window x:Class="LINQ_MVVM_1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModel="clr-namespace:LINQ_MVVM_1.ViewModel"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch"
                      DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                      ItemsSource="{Binding oDoc.View}">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="docIDColumn" Binding="{Binding DocId}" Header="ID" Width="65"/>
            <DataGridTextColumn x:Name="DocumentNumberColumn" Binding="{Binding Number}" Header="Document Number" Width="*"/>
            <DataGridTextColumn x:Name="altIDColumn" Binding="{Binding AltID}" Header="Alt" Width="55"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

And here is the code for the binding reference object, a ViewableCollection, with a filterable view property:

    public class ViewableCollection<T> : ObservableCollection<T>
{
    private ListCollectionView _View;
    public ListCollectionView View
    {
        get
        {
            if (_View == null)
            {
                _View = new ListCollectionView(this);
            }
            return _View;
        }
    }
}

class ObservableDocuments : ViewableCollection<Document>
{
    public ObservableDocuments(DataClasses1DataContext dataDc)
    {
        foreach (Document doc in dataDc.Documents)
        {
            this.Add(doc);
        }
    }
}

Moving the _dataDc and _oDoc into the ViewModel class has resulted in nothing populating the data grid. What am I doing wrong? It seems that getting the ViewModel instantiated is not happening.

Upvotes: 0

Views: 1344

Answers (1)

BradleyDotNET
BradleyDotNET

Reputation: 61379

This line:

DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"

Means that you are still looking at the code-behind for your DataContext. In case you aren't aware, the DataContext defines the root object to which all bindings look at the start of their "Path".

So you're right, the VM isn't being instantiated because you never instantiated it.

Instead, remove that line and in your UI constructor write:

DataContext = new MainViewModel();

There are other ways to do it of course, but thats the simplest.

Upvotes: 1

Related Questions