1
votes

I've got DataGrid bound to an ObservableCollection<> in its ViewModel:

<DataGrid ItemsSource="{Binding Path=Data}" SelectedItem="{Binding Path=CurrentItem}" />

ViewModel:

    public ObservableCollection<TestModel> Data { get; set; }

    private TestModel _currentItem;

    public TestModel CurrentItem
    {
        get { return _currentItem; }
        set
        {
            _currentItem = value;
            RaisePropertyChanged("CurrentItem");
        }
    }

Now what I want is, that the DataGrid will preselect the first Row right on Form-startup. So I put the following in my test-code inside the constructor:

    Data = new ObservableCollection<TestModel>
    {
        new TestModel() { Property1 = Guid.NewGuid().ToString() },
        new TestModel() { Property1 = Guid.NewGuid().ToString() },
        new TestModel() { Property1 = Guid.NewGuid().ToString() }
    };
    CurrentItem = Data[0];

The data is displayed but the first row isn't selected by the grid. Even if I set the binding to TwoWay, it won't work.

If I remove the SelectedItem-binding in XAML and add the following in Code-behind, it works well:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var m = this.DataContext as MainViewModel;
        grid.SelectedItem = m.CurrentItem;
    }
1
Can you try if selecting a row in DataGrid update your view model's CurrentItem property? - Amit
@Amit If you want to know, if the CurrentItem-setter is called when I click a row in the grid then the answer is yes, it is. Even if I leave out the setting for the binding-direction. - Alexander Schmidt
I noticed the same problem and ended up using the same workaround. - RQDQ
@RQDQ Thanks for that. I'm a little bit charmer now ;-) - Alexander Schmidt
How/where do you set your MainViewModel to the DataContext? Because I've created a small repro based on your code and the pre-selection is working fine. - nemesv

1 Answers

1
votes

What's happening is that your VM is being assigned to the data context before the window is initialized and therefore never receives the message that the CurrentItem has changed because it was changed before it loaded.

What I do, is pass in the view model into View's constructor and set it after the InitializeComponent() function is called. Because I am using Prism I am using inversion of control (IOC) and Prism knows to input my VM into the constructor. If you are instantiating your view and view model yourself, you can just pass in the view model. I ran into the same issue and this works.

    public MyView(IMyVM viewModel)
    {
        InitializeComponent();
        this.DataContext = viewModel;
    }

By the way, in working with MVVM, I see no reason not to pass in the ViewModel into the View because the view is dependent on it anyway. I know some people feel differently but it is either this or you will have to so some type of refresh of the datacontext in the Window_Loaded event.