2
votes

I've got a WPF DataGrid, with a single column, that's bound to an ObservableCollection in my ViewModel. User clicks a button that adds a new item to the list. Item is added to the ObservableCollection and the new item shows up in the DataGrid as expected.

Every time the user adds a new item I want to put the new cell into edit mode so the user can edit the name of the item. Not sure how to do this using the MVVM pattern.

1
Do it in code behind. It's just the UI stuff it's not breaking MVVM it's a proper way.MajkeloDev
It is breaking MVVM if you directly bind directly to anything on the ViewModel class as Views and ViewModels are ideally loosely coupled.toadflakz
@toadflakz it's just an event - > user click add then focus textbox. That's all no data being passed ... data operation done via commandMajkeloDev
So you only want a single cell editable following an add item? What is wrong with changing the name of the older objects? Are you using a <DataGridTextColumn>? Can you provide the code?Felix Castor
@MajkeloDev He's using a DataGrid. There is a major difference between just setting focus to a textbox and enabling edit on a DataGrid cell for a newly added item. His data command would raise the event for starting cell edit so the item exists in the DataGrid beforehand. Any communication to tell the View to perform a View specific action, not through binding is technically breaking MVVM. (Yes, Microsoft broke their own interaction pattern with DataGrid).toadflakz

1 Answers

-2
votes

Unfortunately, there is no easy way to do this in an MVVM pattern as the necessary properties on DataGridCell don't exist and edit mode in a DataGrid can only be achieved by calling methods.

The way to minimise the nastiness of the solution is to implement an interface so that the code in your View work against an interface rather than directly interacting with your ViewModel, allowing at least for some level of decoupling. Attach the event handlers for your interface during your DataContextChanged handler in your View.

Ideally your interface should raise an event and you then handle that in the View code-behind to call BeginEdit() on the DataGrid once you've focused your specific cell. Focus the particular cell, start the edit, then focus the now created child editing element control (i.e. a TextBox).

For example:

private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    IRaiseStartCellEditEvent context = DataContext as IRaiseStartCellEditEvent;
    if (context != null)
    {
        context.StartCellEdit += (o, args) =>
        {
            //Get the cell from first row
            var cell = DataGrid.GetCell(0, 2);
            //Focus on the cell for editing
            cell.Focus();
            //Start editing the cell
            DataGrid.BeginEdit();
            //Get the editing textbox
            var tbEditor = Extensions.GetVisualChild<TextBox>(cell);
            //Force the keyboard focus
            if (tbEditor != null)
            {
                Keyboard.Focus(tbEditor);
                tbEditor.SelectAll();
            }
        };
    }
}