Does WPF DataGrid fire an event when a row is added / removed?

前端 未结 7 608
失恋的感觉
失恋的感觉 2021-02-06 05:48

I wish to recalculate things everytime a DataGrid gets more rows or some are removed. I tried to use the Loaded event, but that was fired only once.

I found

相关标签:
7条回答
  • 2021-02-06 06:40

    Have you tried an MVVM approach and binding to an Observable collection?

    public ObservableCollection<Thing> Items{
    get { return _items; }
    set{ _items = value; RaisePropertyChanged("Items");  // Do additional processing here 
    }
    }
    

    So you can watch the add / remove of items without being tied to the UI?

    0 讨论(0)
  • 2021-02-06 06:41

    Depending on what "things" you want to recalculate, you might consider using the ScrollViewer.ScrollChanged attached event. This can be set in XAML as follows:

    <DataGrid
    ...
    ScrollViewer.ScrollChanged="control_ScrollChanged">
    

    The ScrollChangedEventArgs object has various properties that can be helpful for computing layout and scroll position (Extent, Offset, Viewport). Note that these are typically measured in numbers of rows/columns when using the default virtualization settings.

    0 讨论(0)
  • 2021-02-06 06:41

    I was looking for solution to this and I have found the perfect event to handle this, the event is called UnloadingRow

    <DataGrid ....
        UnloadingRow="DataGrid_UnloadingRow">
     ...
    </DataGrid>
    

    In your C# code u get this

    private void ProductsDataGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
    {
       MyObject obj = (MyObject)e.Row.Item; // get the deleted item to handle it
       // Rest of your code ...
       // For example : deleting the object from DB using entityframework
    
    }
    
    0 讨论(0)
  • 2021-02-06 06:43

    If you want you can go down the RowUnloading route as others have described here, however note that this event fires also every time a row is losing focus.

    However by playing around I found that when a row is removed the SelectedItem property of the grid is null while the CurrentItem property is not null, and so far I have seen this combination only for a deleted row, (although I can't guarantee that I have not missed an exotic situation... however for the basic situations of moving away from the row I have not seen it so far).

    So when can use the following code to filter for deleted rows only:

    private void CategoriesGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
    {     
            if (((DataGrid)sender).SelectedItem != null || ((DataGrid)sender).CurrentItem == null)
            {
                return;
            }
    
            // The rest of your code goes here
    }
    
    0 讨论(0)
  • 2021-02-06 06:44

    How about DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)?

    Same for Unloading.

    DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)?

    0 讨论(0)
  • 2021-02-06 06:45

    If your DataGrid is bound to something, I think of two ways of doing this.

    You could try getting the DataGrid.ItemsSource collection, and subscribing to its CollectionChanged event. This will only work if you know what type of collection it is in the first place.

    // Be warned that the `Loaded` event runs anytime the window loads into view,
    // so you will probably want to include an Unloaded event that detaches the
    // collection
    private void DataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        var dg = (DataGrid)sender;
        if (dg == null || dg.ItemsSource == null) return;
    
        var sourceCollection = dg.ItemsSource as ObservableCollection<ViewModelBase>;
        if (sourceCollection == null) return;
    
        sourceCollection .CollectionChanged += 
            new NotifyCollectionChangedEventHandler(DataGrid_CollectionChanged);
    }
    
    void DataGrid_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Execute your logic here
    }
    

    The other solution would be to use an Event System such as Microsoft Prism's EventAggregator or MVVM Light's Messenger. This means your ViewModel would broadcast a DataCollectionChanged event message anytime the bound collection changes, and your View would subscribe to receive these messages and execute your code anytime they occur.

    Using EventAggregator

    // Subscribe
    eventAggregator.GetEvent<CollectionChangedMessage>().Subscribe(DoWork);
    
    // Broadcast
    eventAggregator.GetEvent<CollectionChangedMessage>().Publish();
    

    Using Messenger

    //Subscribe
    Messenger.Default.Register<CollectionChangedMessage>(DoWork);
    
    // Broadcast
    Messenger.Default.Send<CollectionChangedMessage>()
    
    0 讨论(0)
提交回复
热议问题