Hi all, it's a long story, I have to show data in a grid, I were forced to use a datatable to represent records, luckily the radgridview works like a charm with datatables.
When i add a record to the datatable I call Rebind to let the grid stay in sync. And that worked fine for months.
Now the customer wants that when a record is inserted the grid scroll to show the latest record inserted.
So i tried the scrollintoview with no success. Then i used the BringIndexIntoView that worked.
But after the call to BringIndexIntoView the following call to Rebind generate a NullReferenceException.
Also note that if I try to catch the exception and show a standard windows messagebox the messagebox too raise an exception. Seems like the call to BringIndexIntoView messed up the program.
To reproduce the error i created a project if that can help. Just copy into a new VS2010 WPF project named WpfApplication1 using telerik 2010 Q1 SP2 and framework 4.0.
When running click on reset datasource then click twice on add record.
//MainWindow.xaml.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;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;using System.Data;namespace WpfApplication1{ public partial class MainWindow : Window { SampleData sd; public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { BindToNewDS(); } private void BindToNewDS() { sd = new SampleData(50); radGridView1.ItemsSource = sd.TheTable; } private void button2_Click(object sender, RoutedEventArgs e) { int idx = sd.CreateSampleRecord(); radGridView1.Rebind(); DataRow dr = (radGridView1.ItemsSource as DataTable).Rows .Find(new Object[] { idx }); if (radGridView1.Items.Contains(dr)) { int iof = radGridView1.Items.IndexOf(dr); radGridView1.BringIndexIntoView(iof); } } }}MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow" Title="MainWindow" Height="350" Width="525" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="45"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <telerik:RadGridView ShowInsertRow="False" CanUserInsertRows="False" RowHeight="22" SelectionMode="Extended" Grid.Row="1" Name="radGridView1" IsReadOnly="True"> <telerik:RadGridView.Columns> </telerik:RadGridView.Columns> </telerik:RadGridView> <Button Content="Reset datasource" Height="29" HorizontalAlignment="Left" Margin="16,11,0,0" Name="button1" VerticalAlignment="Top" Width="94" Click="button1_Click" /> <Button Content="Add record and scroll to" Height="30" HorizontalAlignment="Left" Margin="132,10,0,0" Name="button2" VerticalAlignment="Top" Width="144" Click="button2_Click" /> </Grid></Window>
//SampleData.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel;using System.Data;namespace WpfApplication1{ class SampleData { //define fixed columns private DataColumn[] fixedColumns = new DataColumn[] { new DataColumn("Equipment", typeof(string)), new DataColumn("Place Of Receipt", typeof(string)), new DataColumn("Port Of Load", typeof(string)), new DataColumn("Port Of Discharge", typeof(string)), new DataColumn("Delivery Place", typeof(string)) }; //define variable columns, only a random subset of these columns will be added to resulting table private DataColumn[] varColumns = new DataColumn[] { new DataColumn("Freight", typeof(decimal)), new DataColumn("Bunker", typeof(decimal)), new DataColumn("Peak season", typeof(decimal)), new DataColumn("Pickup costs", typeof(decimal)), new DataColumn("Delivery costs", typeof(decimal)) }; private string[][] sampleData = new string[][] { new string[] {"Equipment", "20 box", "20 o.t.", "40 box", "40 o.t.", "40 h.c."}, new string[] {"Place Of Receipt", "Lyon", "Tolouse", "Torino", "Milano", "Verona", "Madrid"}, new string[] {"Port Of Load", "Marseille", "Genova", "La Spezia", "Barcelona", "Napoli"}, new string[] {"Port Of Discharge", "New York", "Montreal ramp", "Norfolk", "Miami", "Savannah"}, new string[] {"Delivery Place", "Atlanta", "Jersey City, NJ", "Edison, NJ", "Oaks, PA", "Taftsville, CT"}, }; private Random randGenerator = new Random(); private int LastID = 0; public SampleData(int initialRecordCount) { GenerateTableDefinition(); CreateSampleRecord(); for (int i = 1; i < initialRecordCount; ++i) CreateSampleRecord(); } public int CreateSampleRecord() { var row = m_TheTable.NewRow(); LastID += randGenerator.Next(99)+1; row["ID"] = LastID; m_TheTable.Rows.Add(row); foreach (DataColumn dc in m_TheTable.Columns) { string[] sample; int randIdx; sample = sampleData.FirstOrDefault(a => a[0].Equals(dc.ColumnName)); if (sample != null) { randIdx = randGenerator.Next(sample.Count() - 2); row[dc] = sample[randIdx + 1]; } if (dc.DataType == typeof(decimal)) { row[dc] = (decimal)(randGenerator.Next(60) * 50); } } return LastID; } private void GenerateTableDefinition() { //creating table DataTable dt = new DataTable("FreightRates"); //creating primary key dt.Columns.Add(new DataColumn("ID", typeof(int))); //adding fixed columns to table foreach (DataColumn dc in fixedColumns) { dt.Columns.Add(dc); } //selecting randomly a number of variable columns to be added to the table List<DataColumn> varColumnList = varColumns.ToList(); int numberOfVariableColumns = randGenerator.Next(varColumnList.Count() - 1); for (int i = 0; i < numberOfVariableColumns; ++i) { int randomlySelectedColumn = randGenerator.Next(varColumnList.Count() - 1); dt.Columns.Add(varColumnList[i]); varColumnList.RemoveAt(i); } //expliciting primary key dt.PrimaryKey = new DataColumn[] { dt.Columns["ID"] }; TheTable = dt; } private DataTable m_TheTable; public DataTable TheTable { get { return this.m_TheTable; } private set { if (value != this.m_TheTable) { this.m_TheTable = value; } } } }}
