I am using Editable Datagrid in WPF, when ever i edit the grid like creating new records and hitting a button say for example create button, Then data from my data grid flows properly to the Observable Collection in code behind .cs file. But when i load data to my grid with an excel upload and clicked the create button, then there is no data available in the Observable Collection in code behind. Its weird. Need some help. Find my code samples below
Data grid in XAML:
<DataGrid x:Name="bulkGroupCreationDataGrid" ItemsSource="{Binding BulkGroupCreationModel}" ContextMenuOpening="TheGrid_ContextMenuOpening"
Height="300" CanUserAddRows="True" CanUserDeleteRows="True" CanUserResizeColumns="True" IsManipulationEnabled="True" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" SelectionChanged="bulkGroupCreationDataGrid_SelectionChanged_1">
<DataGrid.Columns>
<DataGridTextColumn Width="100" Header="Group" Binding="{Binding Group, ValidatesOnExceptions=True}" />
<DataGridComboBoxColumn Header="Scope" Width="100" x:Name="Scope"
SelectedValueBinding="{Binding Scope, Mode=TwoWay}"
DisplayMemberPath="{Binding Scope}"/>
<DataGridComboBoxColumn Header="Type" Width="100" x:Name="GroupType"
SelectedValueBinding="{Binding GroupType, Mode=TwoWay}"
DisplayMemberPath="{Binding GroupType}"/>
<DataGridTextColumn Width="100" Header="Description" Binding="{Binding Description, ValidatesOnExceptions=True}" />
<DataGridTextColumn Width="70" Header="OU" Binding="{Binding OU, ValidatesOnExceptions=True}" />
<DataGridTextColumn Width="70" Header="Sub-OU" Binding="{Binding SubOU, ValidatesOnExceptions=True}" />
</DataGrid.Columns>
<DataGrid.CommandBindings>
<CommandBinding Command="{x:Static ApplicationCommands.Paste}"
CanExecute="CanPaste" Executed="Paste"/>
<CommandBinding Command="{x:Static ApplicationCommands.New}"
CanExecute="CanAddNew" Executed="AddNew"/>
</DataGrid.CommandBindings>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/>
<MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
<Button x:Name="Create"
Content="Create"
Click="Create_Click" Foreground="White" FontWeight="Bold" Width="100" Height="25" Background="#5cb85c" RenderTransformOrigin="0.67,0.219" />
Code Behind:
public partial class BulkGroupCreationUserControl : UserControl
{
BulkGroupCreationClass bulkGroupCreationObj = new BulkGroupCreationClass();
private ObservableCollection<BulkGroupCreationModel> _bulkGroupCreationCollection;
public ObservableCollection<BulkGroupCreationModel> BulkGroupCreationCollection
{
get { return _bulkGroupCreationCollection ?? (_bulkGroupCreationCollection = new ObservableCollection<BulkGroupCreationModel>()); }
set { _bulkGroupCreationCollection = value; }
}
//constructor
public BulkGroupCreationUserControl()
{
InitializeComponent();
bulkGroupCreationDataGrid.ItemsSource = BulkGroupCreationCollection;
}
buttonClick Code
private async void Create_Click(object sender, System.Windows.RoutedEventArgs e)
{
//Just checking whether i receive data here, I receive it when data manually typed in grid, but not when uploaded from excel
BulkGroupCreationCollection.Count;
}
Excel to data grid data upload
private void Upload_Click(object sender, RoutedEventArgs e)
{
//Paste here
OpenFileDialog openfile = new OpenFileDialog();
openfile.DefaultExt = ".xlsx";
openfile.Filter = "(.xlsx)|*.xlsx";
//openfile.ShowDialog();
var browsefile = openfile.ShowDialog();
if (browsefile == true)
{
txtFileUpload.Text = openfile.FileName;
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
//Static File From Base Path...........
//Microsoft.Office.Interop.Excel.Workbook excelBook = excelApp.Workbooks.Open(AppDomain.CurrentDomain.BaseDirectory "TestExcel.xlsx", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
//Dynamic File Using Uploader...........
Microsoft.Office.Interop.Excel.Workbook excelBook = excelApp.Workbooks.Open(txtFileUpload.Text.ToString(), 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Microsoft.Office.Interop.Excel.Worksheet excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelBook.Worksheets.get_Item(1); ;
Microsoft.Office.Interop.Excel.Range excelRange = excelSheet.UsedRange;
string strCellData = "";
double douCellData;
int rowCnt = 0;
int colCnt = 0;
System.Data.DataTable dt = new System.Data.DataTable();
for (colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt )
{
string strColumn = "";
strColumn = (string)(excelRange.Cells[1, colCnt] as Microsoft.Office.Interop.Excel.Range).Value2;
dt.Columns.Add(strColumn, typeof(string));
}
for (rowCnt = 2; rowCnt <= excelRange.Rows.Count; rowCnt )
{
string strData = "";
for (colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt )
{
try
{
strCellData = (string)(excelRange.Cells[rowCnt, colCnt] as Microsoft.Office.Interop.Excel.Range).Value2;
strData = strCellData "|";
}
catch (Exception ex)
{
douCellData = (excelRange.Cells[rowCnt, colCnt] as Microsoft.Office.Interop.Excel.Range).Value2;
strData = douCellData.ToString() "|";
}
}
strData = strData.Remove(strData.Length - 1, 1);
dt.Rows.Add(strData.Split('|'));
}
bulkGroupCreationDataGrid.ItemsSource = dt.DefaultView;
excelBook.Close(true, null, null);
excelApp.Quit();
}
}
}
CodePudding user response:
Look at this line in your Upload_Click method:
bulkGroupCreationDataGrid.ItemsSource = dt.DefaultView;
What are you doing here? You are setting the DataGrid's ItemsSource to dt.DefaultView. In other words, when this line is being executed the DataGrid's ItemsSource is not the ObservableCollection anymore, it's dt.DefaultView. Additionally, the Upload_Click method reads the data from the Excel sheet into the DataTable, not into the ObservableCollection. (As a side note, even if your were to set your ItemsSource binding to be in TwoWay mode in an attempt to pass the new ItemsSource value back to the bound (View)Model property, it would quite likely not work without some changes in the respective (View)Model and possibly elsewhere in your code because a DataTable.DefaultView is not convertible to an ObservableCollection.)
Consequently, when Upload_Click is executed, the ObservableCollection provided by the (View)Model used as DataContext remains untouched (because of the Excel data not going into the ObservableCollection, and the DataGrid not using the ObservableCollection as its ItemsSource anymore).
Instead of swapping the ItemsSource of the DataGrid, i suggest you choose either DataTable or ObservableCollection as the type of your DataGrid's ItemsSource and stick with it. Do not manipulate the DataGrid's ItemsSource property directly. If you need to load (or change) content of the DataGrid programmatically (for example as part of the Upload_Click method), alter the DataTable / ObservableCollection instance that is already bound to the DataGrid and is part of the (View)Model that serves as the DataContext for the DataGrid's ItemsSource binding.
If you really need to change the bound DataTable/ObservableCollection to a different DataTable/ObservableCollection instance, change the value of the BulkGroupCreationModel property in the respective (View)Model that serves as DataContext, instead of manipulating the DataGrid's ItemsSource directly in the code-behind.