简体   繁体   中英

WPF DataGrid - Event for New Rows?

I'm using the WPF DataGrid ( .Net 3.5 SP 1 version from the Toolkit )

What event can I subscribe to, to detect when a new row is added? (eg when the user moves the cursor down or presses Enter a new blank row gets added to the grid).

Eventually what I want to do is use that event to calculate some default values and put them in the new row.

The grid is bound to a DataTable , if that makes any difference.

The event you are looking for is DataGrid.AddingNewItem event . This event will allow you to configure the new object as you want it and then apply it to the NewItem property of the AddingNewItemEventArgs .

XAML:

<DataGrid Name="GrdBallPenetrations"
      ItemsSource="{Binding BallPenetrationCollection}" 
      SelectedItem="{Binding CurrentSelectedBallPenetration}"
      AutoGenerateColumns="False" 
      IsReadOnly="False"
      CanUserAddRows="True"
      CanUserDeleteRows="True"
      IsSynchronizedWithCurrentItem="True"
      AddingNewItem="GrdBallPenetrations_AddingNewItem">

Code behind in C#:

private void GrdBallPenetrations_AddingNewItem(object sender,
    AddingNewItemEventArgs e)
{
    e.NewItem = new BallPenetration
    {
        Id              = Guid.NewGuid(),
        CarriageWay     = CariageWayType.Plus,
        LaneNo          = 1,
        Position        = Positions.BetweenWheelTracks
    };
}

Objects are persisted (inserted or updated) when the user leaves a row that he was editing. Moving to another cell in the same row updates the corresponding property through data binding, but doesn't signal the Model (or the Data Access Layer) yet. The only useful event is DataGrid.RowEditEnding. This is fired just before committing the modified row.

XAML

<DataGrid ... 
          RowEditEnding="MyDataGrid_RowEditEnding">
</DataGrid>

Code Behind

private void MyDataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e) 
{    // Only act on Commit
    if (e.EditAction == DataGridEditAction.Commit)
    {
         var newItem = e.Row.DataContext as MyDataboundType;
         if (newItem is NOT in my bound collection) ... handle insertion...
    } 
}

All credits for this solution go to Diederik Krolls ( Original Post ). My respect.

Instead of working on events within your View (the grid), I'd recommend watching the bound object instead, and putting your logic there. This keeps your business logic with your business objects .

Since you're bound to a DataTable , the simplest way is to just subscribe to DataTable.TableNewRow .

I'm adding this because I've just spent close to 2 hours trying to work out how to get the DataGrid to add a new row when you are bound to a collection of view models and you need to control the construction of those view models.

So the setup is that you have an ObservableCollection<MyViewModel> that is bound to the ItemsSource of your DataGrid. You need to create MyViewModel yourself in the view model layer.

This is how the DataGrid appears to function when it adds a row automatically:

  1. When it creates that blank row at the bottom it creates a new instance of MyViewModel it will bind to the row by calling the default constructor on the type. Who knows why it does this, but if MyViewModel does not have a default constructor it will just fail to show that blank row. This is probably the place that you are stuck, because you don't have a default constructor, because you need to create the object yourself. Unfortunately you are going to need to go and add one. Again note that if the element type is an interface this is doomed to failure. The element type of the collection must be a concrete class with a default constructor.
  2. Now it waits until the user goes to edit the row, at which point it starts the add proper.
  3. It raises the AddingNewItem : this is where you can intercept the add operation and switch out the default constructor created instance it has created with your own instance. The AddingNewItemEventArgs.NewItem has a setter and you can swap the current item for your own.

我发现 DataGrid_InitializingNewItem 事件很有用,您可以在其中检查 e.NewItem 并根据其类型采取适当的操作。

AddingNewItem不同, DataGrid.LoadingRow 事件(自 .Net 4.0 起可用)将为通过ItemSource绑定添加的项目触发。

In you XAML, include the following code in your Window tag:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"

Next, inside you DataGrid element, add the following trigger:

<DataGrid ...>

  <i:Interaction.Triggers>
        <i:EventTrigger EventName="LoadingRow">
               <cmd:EventToCommand Command="{Binding LoadRowHandler}" 
                                                PassEventArgsToCommand="True"/>
         </i:EventTrigger>                        
   </i:Interaction.Triggers>

</DataGrid>

Next, in you View Model, add a command for handling the event :

public RelayCommand<DataGridRowEventArgs> LoadRowHandler{ get; private set; }

Inside constructor, initialize the command:

LoadRowHandler = new RelayCommand<DataGridRowEventArgs>(LoadingRowHandlerMethod);

Next, create a method where you want to put the logic:

private void LoadingRowHandlerMethod(DataGridRowEventArgs e)
{
  //....
  //....
}

That's all. Now whenever a new row is added to your DataGrid, the LoadingRowHandlerMethod will get executed.

Hope it helps.

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