Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select multiple items from a DataGrid in an MVVM WPF project

How can I select multiple items from a DataGrid in an MVVM WPF project?

like image 640
Manvinder Avatar asked Apr 04 '14 16:04

Manvinder


People also ask

What is the difference between grid and DataGrid in WPF?

A Grid is a control for laying out other controls on the form (or page). A DataGrid is a control for displaying tabular data as read from a database for example.

Can user add rows DataGrid WPF?

WPF DataGrid (SfDataGrid) provides built-in row called AddNewRow. It allows user to add a new row to underlying collection. You can enable or disable by setting SfDataGrid.

What is DataGrid WPF?

A DataGrid is a control that displays data in a customizable grid. It provides a flexible way to display a collection of data in rows and columns. The hierarchical inheritance of DataGrid class is as follows −


2 Answers

You can simply add a custom dependency property to do this:

public class CustomDataGrid : DataGrid {     public CustomDataGrid ()     {         this.SelectionChanged += CustomDataGrid_SelectionChanged;     }      void CustomDataGrid_SelectionChanged (object sender, SelectionChangedEventArgs e)     {         this.SelectedItemsList = this.SelectedItems;     }     #region SelectedItemsList      public IList SelectedItemsList     {         get { return (IList)GetValue (SelectedItemsListProperty); }         set { SetValue (SelectedItemsListProperty, value); }     }      public static readonly DependencyProperty SelectedItemsListProperty =             DependencyProperty.Register ("SelectedItemsList", typeof (IList), typeof (CustomDataGrid), new PropertyMetadata (null));      #endregion } 

Now you can use this dataGrid in the XAML:

<Window x:Class="DataGridTesting.MainWindow"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"     xmlns:local="clr-namespace:DataGridTesting.CustomDatagrid"     Title="MainWindow"     Height="350"     Width="525">   <DockPanel>     <local:CustomDataGrid ItemsSource="{Binding Model}"         SelectionMode="Extended"         AlternatingRowBackground="Aquamarine"         SelectionUnit="FullRow"         IsReadOnly="True"         SnapsToDevicePixels="True"         SelectedItemsList="{Binding TestSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>   </DockPanel> </Window> 

My ViewModel:

public class MyViewModel : INotifyPropertyChanged {     private static object _lock = new object ();     private List<MyModel> _myModel;      public IEnumerable<MyModel> Model { get { return _myModel; } }      private IList _selectedModels = new ArrayList ();      public IList TestSelected     {         get { return _selectedModels; }         set         {             _selectedModels = value;             RaisePropertyChanged ("TestSelected");         }     }      public MyViewModel ()     {         _myModel = new List<MyModel> ();         BindingOperations.EnableCollectionSynchronization (_myModel, _lock);          for (int i = 0; i < 10; i++)         {             _myModel.Add (new MyModel             {                 Name = "Test " + i,                 Age = i * 22             });         }         RaisePropertyChanged ("Model");     }      public event PropertyChangedEventHandler PropertyChanged;      public void RaisePropertyChanged (string propertyName)     {         var pc = PropertyChanged;         if (pc != null)             pc (this, new PropertyChangedEventArgs (propertyName));     } } 

My model:

public class MyModel {     public string Name { get; set; }     public int Age { get; set; } } 

And finally, here is the code behind of MainWindow:

public partial class MainWindow : Window {     public MainWindow ()     {         InitializeComponent ();         this.DataContext = new MyViewModel ();     } } 

I hope this clean MVVM design helps.

like image 154
Sandesh Avatar answered Sep 22 '22 05:09

Sandesh


What I would do is create Behaviors using System.Windows.Interactivity. You would have to reference it manually in your project.

Given a control which doesn't expose SelectedItems e.g., (ListBox, DataGrid)

You can create a behavior class something like this

public class ListBoxSelectedItemsBehavior : Behavior<ListBox> {     protected override void OnAttached()     {         AssociatedObject.SelectionChanged += AssociatedObjectSelectionChanged;     }      protected override void OnDetaching()     {         AssociatedObject.SelectionChanged -= AssociatedObjectSelectionChanged;     }      void AssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e)     {         var array = new object[AssociatedObject.SelectedItems.Count];         AssociatedObject.SelectedItems.CopyTo(array, 0);         SelectedItems = array;     }      public static readonly DependencyProperty SelectedItemsProperty =         DependencyProperty.Register("SelectedItems", typeof(IEnumerable), typeof(ListBoxSelectedItemsBehavior),          new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));      public IEnumerable SelectedItems     {         get { return (IEnumerable)GetValue(SelectedItemsProperty); }         set { SetValue(SelectedItemsProperty, value); }     } } 

And on your XAML I would do the Binding like this where i is xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" and behaviors is the namespace of your Behavior class

<ListBox>  <i:Interaction.Behaviors>     <behaviors:ListBoxSelectedItemsBehavior SelectedItems="{Binding SelectedItems, Mode=OneWayToSource}" />  </i:Interaction.Behaviors> 

Assuming that your DataContext for the ListBox has the SelectedItems property in the ViewModel then it will automatically update the SelectedItems. You have encapsulated the event subscribing from the View i.e.,

<ListBox SelectionChanged="ListBox_SelectionChanged"/> 

You can change the Behavior class to be of type DataGrid if you want.

like image 28
123 456 789 0 Avatar answered Sep 23 '22 05:09

123 456 789 0