Reputation: 2927
I have an editable DataGrid in a VB WPF application. The DataGrid itself has its SourceUpdated property set to my event handler. 2 of the columns in the grid are editable and have their NotifyOnSourceUpdated flag in the Binding set to True. The event is firing properly, but I can't seem to figure out the best way to determine what has changed. The 2 columns depend on each other in that one of them is an item quantity and the other is a case quantity. If the user changes one of them I want to re-compute the other value and update the grid as well as the binding source. I'm sure there are a number of ways to handle this, but I'm curious what is the best way. I could listen for change event on the datagrid, see what changed, set some variables, and then use those in the SourceUpdated event, but that doesn't seem elegant. Any suggestions?
Upvotes: 0
Views: 376
Reputation: 19885
I suggest you to come out of the world of event handlers! WPF discourages taking the old WinForms approach of doing everything in event handlers.
MVVM way ....
You must leverage the power of your model class in the MVVM way. The bound collection to your datagrid must be a collection of some items... e.g. if you datagrid is showing list of Employees
then your collection must be some IEnumerable<Employee>
... So the Employee
class can help you here.
Assume that your datagrid shows Gender
and Saluation
as two interrelated editable columns. So your Employee
class should have following things in it...
1. `Employee` class must implement `INotifyPropertyChanged` interface.
2. `Gender` and `Salutation` properties must raise the `PropertyChanged` event from their property setters.
3. In the setter of `Gender` \ `Salutation` we must write the logic of changing the other field.
E.g.
private string _gender;
public string Gender
{
get
{
return _gender;
}
set
{
if (_gender != value)
{
_gender = value;
if (_gender == "Male")
{
Salutation = "Mr";
}
else if (_gender == "Female"
&& (Salutation == "Mr" || string.IsNullOrEmpty(Salutation)))
{
Salutation = "Ms";
}
else if (string.IsNullOrEmpty(_gender))
{
Salutation = string.Empty;
}
OnPropertyChanged("Gender");
}
}
}
private string _salutation;
public string Salutation
{
get
{
return _salutation;
}
set
{
if (_salutation != value)
{
_salutation = value;
if (_salutation == "Mrs" || _salutation == "Ms")
{
Gender = "Female";
}
else if (_salutation == "Mr")
{
Gender = "Male";
}
else if (string.IsNullOrEmpty(_salutation))
{
Gender = string.Empty;
}
OnPropertyChanged("Salutation");
}
}
}
Where OnPropertyChanged()
is ...
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This way your GUI will automatically perform the conversion of the related fields.
The ValueConverter way ...
If your fields are not to be stored into the model but are only for display purpose then you can use ValueConverter
....
public class GenderToSalutationConverter : IValueConverter
{
#region IValueConverter Members
public object Convert
(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
var _gender = (string) value;
if (_gender == "Male")
{
return "Mr";
}
else if (_gender == "Female")
{
return "Ms";
}
return string.Empty;
}
public object ConvertBack
(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
var _salutation = (string)value;
if (_salutation == "Mrs" || _salutation == "Ms")
{
return "Female";
}
else if (_salutation == "Mr")
{
return "Male";
}
return string.Empty;
}
#endregion
}
in XAML
<UserControl.Resources>
<local:GenderToSalutationConverter x:Key="GenderToSalutationConverter"/>
</UserControl.Resources>
<tk:DataGrid ItemsSource="{Binding Employees}">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn
Header="Sex"
Binding="{Binding Gender,
Converter={StaticResource GenderToSalutationConverter}}">
</tk:DataGridTextColumn>
<tk:DataGridTextColumn
Header="Title"
Binding="{Binding Salutation}">
</tk:DataGridTextColumn>
</tk:DataGrid.Columns>
</tk:DataGrid>
Hope this helps...
Upvotes: 1