I am new to WPF development yet. I just quickly created a sample to recreate the scenario. I am switching the IsReadonly Property of the datagrid in rowdetailsview based on the checkbox in the parent row.
Everything works fine except in one particular scenario.
How to recreate problem.
Keep the initially create parent row checked. uncheck the parent row. go to the child row id property. clean everything in id field and tab out of that cell and you will see null reference exception.
I have no clue how to fix this issue. Any insight will be really useful.
code behind code:
namespace WpfApplication7
{/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public PerColl People { get; private set; }
public MainWindow()
{
InitializeComponent();
this.People = new PerColl();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
public class Person
: INotifyPropertyChanged, IEditableObject
{
public string Name { get; set; }
public double Salary
{
get { return _salary; }
set
{
if (this._salary == value)
return;
this._salary = value;
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("Salary"));
}
}
public bool IsLocked
{
get { return _isLocked; }
set
{
if (this._isLocked == value)
return;
this._isLocked = value;
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("IsLocked"));
}
}
public ObservableCollection<Kid> Kids { get; set; }
public Person(string name, double salary)
{
this.Name = name;
this.Salary = salary;
}
public Person()
{
this.Salary = 10000;
this.Name = "abc";
this.IsLocked = true;
this.Kids = new ObservableCollection<Kid>();
this.Kids.Add(new Kid(1));
this.Kids.Add(new Kid(2));
}
private bool _isLocked;
private double _salary;
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
public void BeginEdit()
{
if (isEdit) return;
isEdit = true;
this.backup = this.MemberwiseClone() as Person;
}
public void CancelEdit()
{
if (!this.isEdit)
return;
isEdit = false;
this.Name = this.backup.Name;
this.Salary = this.backup.Salary;
}
public void EndEdit()
{
if (this.isEdit == false)
return;
this.isEdit = false;
this.backup = null;
}
private bool isEdit;
private Person backup;
}
public class PerColl : ObservableCollection<Person> { }
public class Kid : IEditableObject,INotifyPropertyChanged
{
public int Id
{
get { return _id; }
set
{
this._id = value;
if (PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("Id"));
}
}
public string Name
{
get { return _name; }
set
{
this._name = value;
if (PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public Person Parent { get; set; }
public Kid()
{
this.Id = 12345;
this.Name = "kidname";
}
public Kid(int id, string name = "kidname")
{
this.Id = 12345;
this.Name = name;
}
#region IEditableObject Members
public void BeginEdit()
{
if (isEdit) return;
isEdit = true;
this.backup = this.MemberwiseClone() as Kid;
}
public void CancelEdit()
{
if (!this.isEdit)
return;
isEdit = false;
this.Id = backup.Id;
}
public void EndEdit()
{
if (this.isEdit == false)
return;
this.isEdit = false;
this.backup = null;
}
#endregion
private int _id;
private string _name;
private bool isEdit;
private Kid backup;
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
}
Xaml Code:
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel LastChildFill="True" Margin="-1,5,1,-5">
<Button Content="Add" Height="30" Click="Button_Click" DockPanel.Dock="Top"/>
<DataGrid ItemsSource="{Binding Path=People}"
AutoGenerateColumns="False"
SelectionUnit="CellOrRowHeader"
RowDetailsVisibilityMode="Visible">
<DataGrid.Columns>
<DataGridTextColumn Header="Salary" Binding="{Binding Path=Salary,StringFormat='{}{0:#,0}'}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
<DataGridCheckBoxColumn Header="IsLocked" Binding="{Binding Path=IsLocked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid
ItemsSource="{Binding Path=Kids}"
AutoGenerateColumns="False"
IsReadOnly="{Binding Path=IsLocked}"
SelectionUnit="CellOrRowHeader">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Path=Id,StringFormat='{}{0:#,0}'}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</DockPanel>