Selecting multiple records in DataGrid with Caliburn.Micro

Selecting multiple records in DataGrid with Caliburn.Micro

I have a WPF application using Caliburn.Micro.

The DataGrid has an attribute SelectedItem="{Binding Path=SelectedUsageRecord}"

As you can see, SelectedItem is bound to SelectedUsageRecord property. But I need to be able to handle selecting multiple records. Is this possible to bind multiple records to a collection property? I don't see anything like "SelectedItems"... Thanks.


Here's what I did after striking the same scenario as you. In short handle the selection change event directly and pull the selected rows from the event args. Assuming a source collection of "Rows" each one being a RowViewModel, and a collection for the "_selectedRows".

<DataGrid RowsSource="{Binding Rows}" x:Name="Rows"                  
          SelectionMode="Extended" SelectionUnit="FullRow">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <cal:ActionMessage MethodName="SelectedRowsChangeEvent">
                <cal:Parameter Value="$eventArgs" />
            </cal:ActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>
public void SelectedRowsChangeEvent(SelectionChangedEventArgs e)
{
    foreach (var addedRow in e.AddedRows)
    {
        _selectedRows.Add(addedRow as RowViewModel);
    }

    foreach (var removedRow in e.RemovedRows)
    {
        _selectedRows.Remove(removedRow as RowViewModel);
    }
}

Selecting multiple records in DataGrid with Caliburn.Micro, I have a WPF application using Caliburn.Micro. The DataGrid has an attribute SelectedItem="{Binding Path=SelectedUsageRecord}". What I am trying to do is selected multiple rows from a dataGrid and return those rows into a bound observable collection. I have tried creating a property(of type) and adding it to an observable collection and it works with single records but the code never fires with multiple records.


I just wanted to post my solution. In Caliburn micro there is no need to set the source as long as you stay true to the naming convention.

Xaml

<DataGrid x:Name="Rows" SelectionMode="Extended" cal:Message.Attach="[Event SelectionChanged] = [Row_SelectionChanged($eventArgs)]">

C#

public List<MyObject> Rows { get; set; }

public MyObject SelectedRow { get; set; } //Will be set by Caliburn Micro. No need to use "SelectedItem={...}"

List<MyObject> _selectedObjects = new List<MyObject>();    

public void Row_SelectionChanged(SelectionChangedEventArgs obj)
{
  _selectedObjects.AddRange(obj.AddedItems.Cast<MyObject>());
  obj.RemovedItems.Cast<MyObject>().ToList().ForEach(w => _selectedObjects.Remove(w));
}

Get the Selected column and row from DataGrid in WPF, As you can see, SelectedItem is bound to SelectedUsageRecord property. But I need to be able to handle selecting multiple records. Is this  Accept Solution Reject Solution. use checkbox column in datagridview. then select the rows by checking the checkbox and use loop to delete selected rows only. Permalink. Posted 10-Sep-12 20:08pm. vijay bisht. Rate this: vote 1 vote 2 vote 3 vote 4 vote 5. Please Sign up or sign in to vote.


Both solutions posted here work fine but they rely on adding a view (wpf) assembly in your viewmodel because of the "SelectionChangedEventArgs" property. This, i think, is not good for cross platform solutions in case you intend to reuse the viewmodels in different platforms.

So, i'm posting my solution that it's more in line with the MVVM pattern. I'm using syncfusion SfDataGrid in this example but this should work fine with a normal DataGrid:

First we need to extend the DataGrid class, so we create a class. I named it "CustomSfDataGrid.cs". Note that i'm also subscribing to the SelectionChanged event and just obtaining the data directly from the "SelectedItems" property.

using System.Windows;
using Caliburn.Micro;
using Syncfusion.UI.Xaml.Grid;

namespace DesktopClient.WPF.Controls
{
    public class CustomSfDataGrid : SfDataGrid
    {
        ///Bindable collection of objects property linked to the DependencyProperty called: "CustomSelectedItems"
        ///We can use "CustomSelectedItems" as a Binding Property in WPF
        public BindableCollection<object> CustomSelectedItems
        {
            get
            {
                return (BindableCollection<object>)GetValue(CustomSelectedItemsProperty);
            }
            set
            {
                SetValue(CustomSelectedItemsProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for SelectedItem.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CustomSelectedItemsProperty = DependencyProperty.Register("CustomSelectedItems", typeof(BindableCollection<object>), typeof(CustomSfDataGrid), new PropertyMetadata(null));

        public CustomSfDataGrid()
        {
            SelectionChanged += CustomSfDataGrid_SelectionChanged;
        }

        private void CustomSfDataGrid_SelectionChanged(object sender, GridSelectionChangedEventArgs e)
        {
            this.CustomSelectedItems = new BindableCollection<object>(this.SelectedItems);
        }
    }
}

In the .xaml file i added a header called "custom" that is pointing to the namespace of my "CustomSfDataGrid.cs". Then, i'm binding the new "CustomSelectedItems" property to "MyViewModelProperty". Finally, i'm using the "SelectionChanged" event.

<UserControl
    xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
    xmlns:cal="http://www.caliburnproject.org"
    xmlns:custom="clr-namespace:DesktopClient.WPF.Controls">
    <Grid>
        <custom:CustomSfDataGrid x:Name="dataGrid" ItemsSource="{Binding Models}" 
                                    SelectionMode="Extended" SelectionChanged="OnSelectionChanged"
                                    CustomSelectedItems="{Binding MyViewModelProperty, Mode=OneWayToSource}">
            <syncfusion:SfDataGrid.Columns>
                <!-- Column Schema -->
            </syncfusion:SfDataGrid.Columns>
        </custom:CustomSfDataGrid>
    </Grid>

Finally, in the ViewModel i have a "BindableCollection" property.

using using System.Linq;
//
//...
        private BindableCollection<object> _myViewModelProperty;

        public BindableCollection<object> MyViewModelProperty
        {
            get
            {
                return _myViewModelProperty;
            }
            set
            {
                _myViewModelProperty = value;
            }
        }

        //
        public void UsingMyViewModel()
        {
            //cast the collection of objects to a different type using linq
            BindableCollection<MyCastedType> x = new BindableCollection<BrandModel>(MyViewModelProperty.OfType<BrandModel>());

            //alternative casting method
            BindableCollection<MyCastedType> y = new BindableCollection<MyCastedType>();
            foreach (var item in MyViewModelProperty)
            {
                y.Add(item as MyCastedType);
            }
        }

WPF Controls with MVVM: DataGrid, Hello , I'm trying to select items using mvvm from datagrid control I'have achieved the selected item selection using mvvm but ho. Is it possible to select multiple records (rows) in "DataGrid" Because I can't find any properties to enable for multiple selection. Yes.. Just press ctrl while you selecting items. delete all selected items? I not sure you can do this. Your code just remove bookmark not remove the items. Datagrid currently using for displaying data from database.


How to enable datagrid control multiple rows selection using mvvm, The SelectionMode property is used for selecting single/multiple row and columns. This property is an enum which have two values: Single; Extended (​Default)  Yeah, this solution is better than hacking into the DataGrid control, and if you want to select only one row you can also use the following code: myDataGrid.SelectedItem = item; where the item is one of the items bound the DataGrid.


WPF DataGrid - Selection Mode, But I want to use Multiple rows with SelectionMode="Multiple" This will let you maintain MVVM and still use the DataGrid's SelectionChanged  For using this code, the user has to have a DataGrid with multiple columns. In that DataGrid for multiple selection of rows, take a template column containing a CheckBox. After that, take a hidden template column containing a Label control with the primary key. All this can be done with the DataGrid property builder and in that the user can create a column and bind data to the DataGrid.


Binding multi selected items in MVVM in UI for Universal Windows , This gives you a nice way of doing View-First MVVM if you so desire. String values are used to resolve an instance from the IoC container. You can specify literals as parameters as well and even declare multiple actions by separating  I need to select multiple rows in a DataGridView (MultiSelect = true, SelectionMode = RowHeaderSelect). From the user interface there is no problem. I simply hold down the <CTRL> key and click on all of the row headers one-by-one.