Dear All,
I have written some logic using MVVM pattern and tried to show a sub-datagrid in each row of a datagrid however there are some issues that I am currently facing and they are as follows (screenshot attached) :-
In each row I have an expander in which I want to control the RowDetailsVisibilityMode of my sub datagrid.
For selected checkboxes the rows should be deleted when clicked on Delete button at the end.
Upon clicking of the Edit button, one can edit a particular row and again the rows become readonly.
Please suggest some approach on how to do this and kindly find my code as follows :-
View :-
<UserControl x:Class="WIMOProjectDemo.View.CustomerManagementModule"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:km="clr-namespace:WIMOProjectDemo.ViewModel"
xmlns:prop="clr-namespace:WIMOProjectDemo.Properties"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:interatComm="clr-namespace:InteractivityHelper"
mc:Ignorable="d"
MinHeight="400" MinWidth="600">
<UserControl.DataContext>
<km:CustomerManagementModuleVM></km:CustomerManagementModuleVM>
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate x:Key="SubGridData">
<TabControl Width="Auto" Height="Auto" Margin="50,0,0,0">
<TabItem Header="Other Contacts">
<DataGrid Width="Auto" Height="Auto" Background="AliceBlue" ItemsSource="{Binding SubGridData}"
GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Name" Binding="{Binding Path=Name}" />
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Email" Binding="{Binding Path=Email}" />
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Phone" Binding="{Binding Path=Phone}" />
</DataGrid.Columns>
</DataGrid>
</TabItem>
<TabItem Header="Billing Address">
<TextBlock Text="This is Billing Address" HorizontalAlignment="Center" VerticalAlignment="Center" />
</TabItem>
<TabItem Header="Delivery Address">
<DataGrid Width="Auto" Height="Auto" Background="DarkGoldenrod" ItemsSource="{Binding SubGridData}"
GridLinesVisibility="None" >
<DataGrid.Columns>
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Name" Binding="{Binding Path=Name}" />
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Email" Binding="{Binding Path=Email}" />
<DataGridTextColumn Width="60" IsReadOnly="True" Header="Phone" Binding="{Binding Path=Phone}" />
</DataGrid.Columns>
</DataGrid>
</TabItem>
<TabItem Header="Other Information">
<TextBlock Text="This is Other Information" HorizontalAlignment="Center" VerticalAlignment="Center" />
</TabItem>
</TabControl>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.10*"/>
<RowDefinition Height="0.02*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="0.02*"/>
<RowDefinition Height="0.10*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<TextBox Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="250" Height="25"
x:Name="txt" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<Grid Grid.Row="1">
<TextBlock />
</Grid>
<Grid Grid.Row="2">
<DataGrid x:Name="dgrd" ItemsSource="{Binding lstsource, UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True" RowDetailsTemplate="{StaticResource SubGridData}"
RowDetailsVisibilityMode="Collapsed"
CanUserAddRows="True" RowBackground="LightBlue" AlternatingRowBackground="AliceBlue"
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Background="Gainsboro"
Width="Auto" Height="Auto" BorderThickness="10" UseLayoutRounding="True" CanUserDeleteRows="False"
IsTextSearchEnabled="True" GridLinesVisibility="None" AutoGenerateColumns="False">
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="MouseDoubleClick" Handler="RowDoubleClick"/>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkSelectRow" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding Path=DataContext.DelegateCommandEdit, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding ElementName=dgrd}">
<Image Source="/WIMOProjectDemo;component/Images/edit icon.png"></Image>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Expander x:Name="SubGridExpander">
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<interatComm:InteractiveCommand Command="{Binding DelegateCommandExpanded}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Collapsed">
<interatComm:InteractiveCommand Command="{Binding DelegateCommandCollapsed}"/>
</i:EventTrigger>
</i:Interaction.Triggers>-->
</Expander>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Customer" Binding="{Binding Path=Customer}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Name" Binding="{Binding Path=Name}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Access" Binding="{Binding Path=Access}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Email" Binding="{Binding Path=Email}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Phone" Binding="{Binding Path=Phone}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Fax" Binding="{Binding Path=Fax}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="First" Binding="{Binding Path=First}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Last" Binding="{Binding Path=Last}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Country" Binding="{Binding Path=Country}" />
<DataGridTextColumn MinWidth="75" IsReadOnly="True" Header="Payment" Binding="{Binding Path=Payment}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
<Grid Grid.Row="3">
<TextBlock />
</Grid>
<Grid Grid.Row="4">
<Button x:Name="btnDeleteSelectedRows" Width="150" HorizontalAlignment="Left" VerticalAlignment="Center"
Margin="15,0,0,0" Content="{x:Static prop:Resources.DeleteButtonText}"
Command="{Binding Path=DelegateCommandDelete, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding ElementName=dgrd}" />
</Grid>
</Grid>
</UserControl>
ViewModel :-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Data;
using Microsoft.Practices.Prism.Commands;
namespace WIMOProjectDemo.ViewModel
{
public class CustomerManagementModuleVM : INotifyPropertyChanged
{
#region Fields
private ICollectionView _lstsource;
private string _filterText;
private DelegateCommand<DataGrid> _delegateCommandDelete;
private DelegateCommand<DataGrid> _delegateCommandEdit;
#endregion
#region Public Variables
public ObservableCollection<ChildGridClass> sublst;
#endregion
#region Properties
public ICollectionView lstsource
{
get { return _lstsource; }
set
{
_lstsource = value;
OnPropertyChanged("lstsource");
}
}
public string FilterText
{
get { return _filterText; }
set
{
_filterText = value;
OnPropertyChanged("FilterText");
FilterCollection();
}
}
#endregion
#region Commands
public DelegateCommand<DataGrid> DelegateCommandDelete
{
get
{
return this._delegateCommandDelete ?? new DelegateCommand<DataGrid>(FireMethod);
}
}
public DelegateCommand<DataGrid> DelegateCommandEdit
{
get
{
return this._delegateCommandEdit ?? new DelegateCommand<DataGrid>(EditRowOnEditButton);
}
}
#endregion
#region Constructors
public CustomerManagementModuleVM()
{
FillDataInGrid();
lstsource = CollectionViewSource.GetDefaultView(ParentGridData);
lstsource.Filter = new Predicate<object>(Filter);
}
#endregion
#region Public Methods
public bool Filter(object obj)
{
var data = obj as ParentGridClass;
if (data != null)
{
if (!string.IsNullOrEmpty(_filterText))
{
return data.Customer.Equals(_filterText) || data.Name.Equals(_filterText) || data.Access.Equals(_filterText) || data.Email.Equals(_filterText) || data.Phone.Equals(_filterText) || data.Fax.Equals(_filterText) || data.Country.Equals(_filterText) || data.Payment.Equals(_filterText);
}
return true;
}
return false;
}
public IEnumerable<ParentGridClass> ParentGridData
{
get
{
yield return new ParentGridClass { Customer = 324234, Name = "sgsfdd", Access = "Private", Email = "sdf@sfd.com", Phone = 56565, Fax = 45454, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "India", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 65464, Name = "bdcgdf", Access = "Public", Email = "dfgfg@sfd.com", Phone = 54646, Fax = 45443, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "India", Payment = "Cheque", SubGridData = sublst };
yield return new ParentGridClass { Customer = 53432, Name = "dsaf", Access = "Public", Email = "hg@sfd.com", Phone = 23423, Fax = 86786, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "India", Payment = "Cash", SubGridData = sublst };
yield return new ParentGridClass { Customer = 68767, Name = "ghgf", Access = "Private", Email = "sdf@sfd.com", Phone = 56785, Fax = 85464, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "India", Payment = "Cheque", SubGridData = sublst };
yield return new ParentGridClass { Customer = 345, Name = "ytryh", Access = "Private", Email = "fgdg@sfd.com", Phone = 54546, Fax = 89878, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "Germany", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 655, Name = "ret", Access = "Private", Email = "cvbcvb@sfd.com", Phone = 98797, Fax = 32433, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "Germany", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 234234, Name = "fghfgh", Access = "Public", Email = "dgdfsd@sfd.com", Phone = 67886, Fax = 56555, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "Germany", Payment = "Cheque", SubGridData = sublst };
yield return new ParentGridClass { Customer = 678678, Name = "cvxcv", Access = "Public", Email = "fdgfg@sfd.com", Phone = 56567, Fax = 45777, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "Germany", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 97887, Name = "vbnvn", Access = "Public", Email = "dfgh@sfd.com", Phone = 87990, Fax = 43555, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "US", Payment = "Cash", SubGridData = sublst };
yield return new ParentGridClass { Customer = 546, Name = "adsasd", Access = "Public", Email = "dfg@sfd.com", Phone = 87900, Fax = 43533, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "US", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 54677, Name = "uyiui", Access = "Public", Email = "sdfds@sfd.com", Phone = 65756, Fax = 56666, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "US", Payment = "Card", SubGridData = sublst };
yield return new ParentGridClass { Customer = 8977, Name = "qweqwe", Access = "Private", Email = "tyry@sfd.com", Phone = 98089, Fax = 34577, First = DateTime.Now.ToShortDateString(), Last = DateTime.Now.ToShortDateString(), Country = "US", Payment = "Cash", SubGridData = sublst };
}
}
#endregion
#region Private Methods
private void FillDataInGrid()
{
sublst = new ObservableCollection<ChildGridClass>();
sublst.Add(new ChildGridClass() { Name = "dsf", Email = "asd@dsa.com", Phone = 4566555 });
sublst.Add(new ChildGridClass() { Name = "rty", Email = "fhg@dsa.com", Phone = 3243433 });
sublst.Add(new ChildGridClass() { Name = "hjk", Email = "cvx@dsa.com", Phone = 9788887 });
sublst.Add(new ChildGridClass() { Name = "qwe", Email = "ret@dsa.com", Phone = 2254884 });
}
private void FireMethod(DataGrid e)
{
ObservableCollection<ParentGridClass> lstsourceNew = lstsource as ObservableCollection<ParentGridClass>;
for (int i = 0; i < e.Items.Count - 1; i++)
{
CheckBox x = e.Columns[0].GetCellContent(e.Items[i]) as CheckBox;
if (x.IsChecked == true)
{
MessageBox.Show(e.Items.Count.ToString());
lstsourceNew.RemoveAt(i);
lstsource = lstsourceNew as ICollectionView;
OnPropertyChanged("lstsource");
}
}
MessageBox.Show("Deleted");
}
private void FilterCollection()
{
if (_lstsource != null)
{
_lstsource.Refresh();
}
}
private void EditRowOnEditButton(DataGrid e)
{
OnPropertyChanged("lstsource");
MessageBox.Show("Edited");
}
#endregion
#region OnPropertyChangedEvent
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
#region Public Classes
public class ParentGridClass
{
public int Customer { get; set; }
public string Name { get; set; }
public string Access { get; set; }
public string Email { get; set; }
public int Phone { get; set; }
public int Fax { get; set; }
public string First { get; set; }
public string Last { get; set; }
public string Country { get; set; }
public string Payment { get; set; }
public ObservableCollection<ChildGridClass> SubGridData { get; set; }
}
public class ChildGridClass
{
public string Name { get; set; }
public string Email { get; set; }
public int Phone { get; set; }
}
#endregion
}
xaml.cs :-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WIMOProjectDemo.View
{
/// <summary>
/// Interaction logic for CustomerManagementModule.xaml
/// </summary>
public partial class CustomerManagementModule : UserControl
{
public CustomerManagementModule()
{
InitializeComponent();
}
private void RowDoubleClick(object sender, RoutedEventArgs e)
{
var row = (DataGridRow)sender;
row.DetailsVisibility = row.DetailsVisibility == Visibility.Collapsed ?
Visibility.Visible : Visibility.Collapsed;
}
}
}