I have implemented a DataGrid as follows:
<DataGrid Name="grdSignals" Grid.Column="1" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Signal Name" Binding="{Binding SignalName}"/>
<DataGridTextColumn Header="Value" Binding="{Binding SignalValue}" />
</DataGrid.Columns>
</DataGrid>
The following is the Class where I implemented the properties used in an ObservableCollection:
namespace Test
{
public partial class MyMain : UserControl
{
public ObservableCollection<Signals> ocSignalNames;
Signals time, mode;
public MyMain()
{
InitializeComponent();
ocSignalNames = new ObservableCollection<Signals>();
time = new Signals() { SignalName = "Time", SignalValue = "" };
mode = new Signals() { SignalName = "Mode", SignalValue = "" };
ocSignalNames.Add(time);
ocSignalNames.Add(mode);
grdSignals.DataContext = ocSignalNames;
}
}
public class Signals : INotifyPropertyChanged
{
string _signalName, _signalValue;
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged(SignalValue);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
After debugging it, I found that the ocSignalNames is getting updated when its items change. But the changes are not getting reflected in the DataGrid. I am updating the Items in a thread like this:
time.SignalValue = iTest1.ToString();
mode.SignalValue = iTest2.ToString();
What am I missing out?
You are missing the correct NotifyChanged handlers:
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
OnPropertyChanged("SignalName"); //Added
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged("SignalValue"); //NOTE: quotation marks added
}
}
you have to use below mentioned code.
string _signalName, _signalValue;
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
OnPropertyChanged("SignalName");
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged(SignalValue);
}
}
your XAML look like
<DataGrid Name="grdSignals" Grid.Column="1" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Signal Name" Binding="{Binding SignalName, Mode=TwoWay}"/>
<DataGridTextColumn Header="Value" Binding="{Binding SignalValue, Mode=TwoWay}" />
</DataGrid.Columns>
</DataGrid>
O/P
Related
Please take a look at the picture first.
When the user enter the number x and mcX, after his modification to that cell, X' should be automatically calculated and shown on the table.
However, if I modify the value of X and mcX, it will reflect on the table, and on the code behind, I can see the X' is modified correctly, but it does not show up. It will only show up when I try to modify its cell.
And also, I am not doing any operation to the database.
Here is the code,
MainWindow.xaml
<DataGrid Name="PupilGrid" HeadersVisibility="All" SelectionUnit="CellOrRowHeader" AutoGenerateColumns="False"
CanUserAddRows="True" CanUserSortColumns="True" CanUserResizeColumns="True" IsReadOnly="False"
ItemsSource="{Binding}" CellEditEnding="PupilGrid_OnCellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="Frame Number" Binding="{Binding FrameNum, Mode=TwoWay}" />
<DataGridTextColumn Header="X" Binding="{Binding ObservedCenterX, Mode=TwoWay}" />
<DataGridTextColumn Header="Y" Binding="{Binding ObservedCenterY}" />
<DataGridTextColumn Header="mcX" Binding="{Binding MedicalCanthusPositionX}" />
<DataGridTextColumn Header="mcY" Binding="{Binding MedicalCanthusPositionY}" />
<DataGridTextColumn Header="X'" Binding="{Binding RelativePupilCenterX}" />
<DataGridTextColumn Header="Y'" Binding="{Binding RelativePupilCenterY}" />
</DataGrid.Columns>
</DataGrid>
MainWindow.xaml.cs
private MainViewModel vm = new MainViewModel();
public MainWindow()
{
InitializeComponent();
vm.PupilList = new ObservableCollection<Pupil>();
vm.PupilList.Add(new Pupil()
{
ObservedCenterX = 2.0,
ObservedCenterY = 1.1,
MedicalCanthusPositionX = 3.3,
MedicalCanthusPositionY = 4.2,
FrameNum = 4
});
vm.updatePupilList();
PupilGrid.ItemsSource = vm.PupilList;
}
private void PupilGrid_OnCellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
vm.updatePupilList();
}
MainViewModel.cs
public class MainViewModel : ViewModelBase, INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private double MedicalCanthusX = 29.02;
private double MedicalCanthusY = 16.50;
private Pupil _Model;
public Pupil Model
{
get => _Model;
set
{
if (_Model != value)
{
_Model = value;
// raise property change
// on modal change
}
}
}
private ObservableCollection<Pupil> _pupilList;
public ObservableCollection<Pupil> PupilList
{
get => _pupilList;
set
{
_pupilList = value;
Debug.WriteLine(value);
Debug.WriteLine("new value added");
updatePupilList();
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterX"));
}
}
public void updatePupilList()
{
foreach (var pupil in PupilList)
{
pupil.RelativePupilCenterX = pupil.ObservedCenterX - pupil.MedicalCanthusPositionX;
pupil.RelativePupilCenterY = pupil.ObservedCenterY - pupil.MedicalCanthusPositionY;
}
}
}
Pupil.cs
public class Pupil : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private double _observedCenterX;
public double ObservedCenterX
{
get => _observedCenterX;
set
{
_observedCenterX = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterX"));
PropertyChanged(this, new PropertyChangedEventArgs("ObservedCenterX"));
}
}
private double _ObservedCenterY;
public double ObservedCenterY
{
get => _ObservedCenterY;
set
{
_ObservedCenterY = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterY"));
PropertyChanged(this, new PropertyChangedEventArgs("ObservedCenterY"));
}
}
private double _medicalCanthusPositionX;
public double MedicalCanthusPositionX
{
get => _medicalCanthusPositionX;
set
{
_medicalCanthusPositionX = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterX"));
PropertyChanged(this, new PropertyChangedEventArgs("MedicalCanthusPositionX"));
}
}
private double _medicalCanthusPositionY;
public double MedicalCanthusPositionY
{
get => _medicalCanthusPositionY;
set
{
_medicalCanthusPositionY = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterY"));
PropertyChanged(this, new PropertyChangedEventArgs("MedicalCanthusPositionY"));
}
}
private double _relativePupilCenterX;
public double RelativePupilCenterX
{
get => _relativePupilCenterX;
set
{
_relativePupilCenterX = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterX"));
}
}
private double _relativePupilCenterY;
public double RelativePupilCenterY
{
get => _relativePupilCenterY;
set
{
_relativePupilCenterY = value;
PropertyChanged(this, new PropertyChangedEventArgs("RelativePupilCenterY"));
}
}
public int FrameNum { get; set; }
}
CellEditEnding is triggerred before your edit is committed, TextBox's text is updated on lostfocus by default.
So, your updatePupilList is called before your X is changed
I want to Refresh my DataGrid and found the following coding on the web:
dataGridView.ItemsSource = null;
dataGridView.ItemsSource = ItemsSourceObjects;
It does work except for the string/column Names does not get displayed with the objects only the objects/items itself.
Any Ideas on why this is happening?
EDIT:
<DataGridTextColumn Binding="{Binding TId}" Header="id" MinWidth="20" MaxWidth="60"/>
<DataGridTextColumn Binding="{Binding TChassisManufacturer}" Header="Project Name" MinWidth="122" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding ProjectStatusM}" Header="Status" MinWidth="122" MaxWidth="100"/>
Here is an example:
You don't need to call refresh. When you add/delete items from my, dg will auto update for you.
XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<DataGrid Name="dataGridView" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding TId}" Header="id" MinWidth="20" MaxWidth="60"/>
<DataGridTextColumn Binding="{Binding TChassisManufacturer}" Header="Project Name" MinWidth="122" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding ProjectStatusM}" Header="Status" MinWidth="122" MaxWidth="100"/>
</DataGrid.Columns>
</DataGrid>
</Window>
C#:
public partial class MainWindow : Window
{
ObservableCollection<myClass> my = new ObservableCollection<myClass>();
public MainWindow()
{
InitializeComponent();
dataGridView.DataContext = my;
my.Add(new myClass { TId = 1, TChassisManufacturer = "Sony", ProjectStatusM = "Done" });
my.Add(new myClass { TId = 2, TChassisManufacturer = "Apple", ProjectStatusM = "Doing" });
}
}
class myClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int id;
public int TId
{
get
{
return id;
}
set
{
id = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("TId"));
}
}
string name;
public string TChassisManufacturer
{
get
{
return name;
}
set
{
name = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("TChassisManufacturer"));
}
}
string status;
public string ProjectStatusM
{
get
{
return status;
}
set
{
status = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("ProjectStatusM"));
}
}
}
After having created my DataBase with Entity Framework, I have created 4 observable Collections containing the 4 tables I have, and a CompositeCollection to regroup'em, like this:
class ViewModel:INotifyPropertyChanged
{
private BDDInterneEntities _BDDInterneEntities;
public ViewModel()
{
_BDDInterneEntities = new BDDInterneEntities();
ResultatCollection = new ObservableCollection<Resultat>(_BDDInterneEntities.Resultat);
D98EquipementsCollection = new ObservableCollection<D98Equipements>(_BDDInterneEntities.D98Equipements);
D98DetailsCollection = new ObservableCollection<D98Details>(_BDDInterneEntities.D98Details);
D675Collection = new ObservableCollection<D675>(_BDDInterneEntities.D675);
cmpc = new CompositeCollection();
CollectionContainer cc1 = new CollectionContainer();
CollectionContainer cc2 = new CollectionContainer();
CollectionContainer cc3 = new CollectionContainer();
CollectionContainer cc4 = new CollectionContainer();
cc1.Collection = ResultatCollection;
cc2.Collection = D98EquipementsCollection;
cc3.Collection = D98DetailsCollection;
cc4.Collection = D675Collection;
cmpc.Add(cc1);
cmpc.Add(cc2);
cmpc.Add(cc3);
cmpc.Add(cc4);
}
public ObservableCollection<Resultat> ResultatCollection { get; set; }
public ObservableCollection<D98Equipements> D98EquipementsCollection { get; set; }
public ObservableCollection<D98Details> D98DetailsCollection { get; set; }
public ObservableCollection<D675> D675Collection { get; set; }
public CompositeCollection cmpc {get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
What I look for is to bind some values of one ObservaleCollection to one DataGridTextColumn, some values of another ObservableCollection to one anotherDataGridTextColumn, etc.
This is the Datagrid, target of the binding:
<DataGrid x:Name="DonneesBrutes" IsReadOnly="True" ItemsSource="{Binding Path=.cmpc}" Margin="10,65,0,0" AutoGenerateColumns="False" EnableRowVirtualization="True" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding .Remarque}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn x:Name="PMRQ" Width="*" Binding="{Binding Path=.PMID}" Header="PMID"></DataGridTextColumn>
<DataGridTextColumn x:Name="LibellePMRQ" Width="*" Binding="{Binding Path=.LibelléTOTApres}" Header="Libellé PMRQ"></DataGridTextColumn>
<DataGridTextColumn x:Name="Ligne" Width="*" Binding="{Binding Path=.Remarque}" Header="Ligne" IsReadOnly="True"></DataGridTextColumn>
<DataGridTextColumn x:Name="OTM" Width="*" Binding="{Binding Path=.TOTMPMRQ}" Header="OTM"></DataGridTextColumn>
<DataGridTextColumn x:Name="TOTM" Width="*" Binding="{Binding Path=.SiModifie}" Header="TOTM"></DataGridTextColumn>
<DataGridTextColumn x:Name="LibelleTOTM" Width="*" Binding="{Binding Path=.LibelléTOTApres}" Header="Libellé OTM"></DataGridTextColumn>
<DataGridTextColumn x:Name="GA" Width="*" Binding="{Binding Path=.Groupe_D_alerte}" Header="GA"></DataGridTextColumn>
<DataGridTextColumn x:Name="Discipline" Width="*" Binding="{Binding Path=.NomTable}" Header="Discipline"></DataGridTextColumn>
<DataGridTextColumn x:Name="DisciplineSubstituee" Width="120" Binding="{Binding Path=.NomChamp}" Header="Discipline Substituée"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
The first DataGridTextColumn is binded from the D98DetailsCollection, the second one is binded from the ResultatCollection, etc. As the following condition : The property TOTMPMRQ which is a common column of each ObservableCollection are equals.
For example, for a TOTMPMRQ like 123456789, I wand to bind the PMRQ value of the D98DetailsCollection in the first DataGridTextColumn where TOTMPMRQ equals 123456789, then bind the libellePMRQ value of the ResultatCollection in the second DataGridTextColumn where TOTMPMRQ still equals 123456789, etc for each DataGridTextColumn to get on one line values from severals ObservableCollections.
My main difficulty is to make this if condition. Currently, the DataGrid only print ObservableCollection after ObservableCollection, and not a combined result.
I hope I'm not too disordered on my explanations, I always can Edit my post if needed, don't hesitate to ask me more, or less...
Thanks in advance for your help.
EDIT1:
I have created a class TestCollectionList which inherit of an ObservableCollection called TestCollection, like this:
public class TestCollectionList : ObservableCollection<TestCollectionList.TestCollection>
{
public TestCollectionList() : base()
{
Add( new TestCollection());
}
public class TestCollection
{
private string pmid;
private string libellepmrq;
private string ligne;
private string otm;
private string totm;
private string libelleotm;
private string ga;
private string discipline;
private string disciplinesubstituee;
public TestCollection(string pmid, string libellepmrq, string ligne, string otm, string totm, string libelleotm, string ga, string discipline, string disciplinesubstituee)
{
this.pmid = pmid;
this.libellepmrq = libellepmrq;
this.ligne = ligne;
this.otm = otm;
this.totm = totm;
this.libelleotm = libelleotm;
this.ga = ga;
this.discipline = discipline;
this.disciplinesubstituee = disciplinesubstituee;
}
public string Pmid
{
get { return pmid; }
set { pmid = value; }
}
public string Libellepmrq
{
get { return libellepmrq; }
set { pmid = value; }
}
public string Ligne
{
get { return ligne; }
set { pmid = value; }
}
public string Otm
{
get { return otm; }
set { pmid = value; }
}
public string Totm
{
get { return totm; }
set { pmid = value; }
}
public string Libelleotm
{
get { return libelleotm; }
set { pmid = value; }
}
public string Ga
{
get { return ga; }
set { pmid = value; }
}
public string Discipline
{
get { return discipline; }
set { pmid = value; }
}
public string Disciplinesubstituee
{
get { return disciplinesubstituee; }
set { pmid = value; }
}
}
}
I have created every properties I want to bind in my DataGridTextColumn and now I want to set them with their values of the differents valus of my DataBase. For example, pmid must be equal of the PMID property of the ObservableCollection D98DetailsCollection, ga must be set the GA property of the ObservableCollection ResultatCollection, etc.
Am I on the good way, Am I definitly wrong? Thanks in advance.
I am creating a WPF application that will use IDataErrorInfo data validation, which my business objects implement. Now I want to list all the validation errors to the user in a messagebox when the user clicks the save button. How to acheive this?
My Datagrid is:
<my:DataGrid Name="dgReceiveInventory" RowStyle="{StaticResource RowStyle}" ItemsSource="{Binding}" GotFocus="dgReceiveInventory_GotFocus" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" RowHeight="23" SelectionUnit="Cell" AutoGenerateColumns="False" Margin="12,84,10,52" BeginningEdit="dgReceiveInventory_BeginningEdit">
<my:DataGrid.Columns>
<!--0-Product Column-->
<my:DataGridTemplateColumn Header="Product Name" Width="200">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource TextBlockInError}" Text="{Binding ProductName,ValidatesOnDataErrors=True}" ></TextBlock>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
<my:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox x:Name="txtbxProduct" Text="{Binding Path=ProductName,UpdateSourceTrigger=LostFocus,ValidatesOnDataErrors=True}" TextChanged="txtbxProduct_TextChanged" PreviewKeyDown="txtbxProduct_PreviewKeyDown" >
</TextBox>
</DataTemplate>
</my:DataGridTemplateColumn.CellEditingTemplate>
</my:DataGridTemplateColumn>
<!--1-Purchase Rate Column-->
<my:DataGridTextColumn Header="Purchase Rate" Width="100" Binding="{Binding PurchaseRate}" IsReadOnly="True"></my:DataGridTextColumn>
<!--2-Avaialable Qty Column-->
<my:DataGridTextColumn Header="Stock" Binding="{Binding AvailableQty}" IsReadOnly="True" Visibility="Hidden"></my:DataGridTextColumn>
<!--4-Amount Column-->
<my:DataGridTextColumn Header="Amount" Width="100" Binding="{Binding Amount}" ></my:DataGridTextColumn>
</my:DataGrid.Columns>
</my:DataGrid>
My Object is:
class clsProducts : INotifyPropertyChanged, IDataErrorInfo
{
private string _ProductName;
private decimal _PurchaseRate;
private int _AvailableQty;
private int _Qty;
private decimal _Amount;
#region Property Getters and Setters
public string ProductName
{
get { return _ProductName; }
set
{
if (_ProductName != value)
{
_ProductName = value;
OnPropertyChanged("ProductName");
}
}
}
public decimal PurchaseRate
{
get { return _PurchaseRate; }
set
{
_PurchaseRate = value;
OnPropertyChanged("PurchaseRate");
}
}
public int AvailableQty
{
get { return _AvailableQty; }
set
{
_AvailableQty = value;
OnPropertyChanged("AvailableQty");
}
}
public int Qty
{
get { return _Qty; }
set
{
_Qty = value;
this._Amount = this._Qty * this._PurchaseRate;
OnPropertyChanged("Qty");
OnPropertyChanged("Amount");
}
}
public decimal Amount
{
get { return _Amount; }
set
{
_Amount = value;
OnPropertyChanged("Amount");
}
}
#endregion
#region IDataErrorInfo Members
public string Error
{
get
{
return "";
}
}
public string this[string name]
{
get
{
string result = null;
if (name == "ProductName")
{
if (this._ProductName != null)
{
int count = Global.ItemExist(this._ProductName);
if (count == 0)
{
result = "Invalid Product";
}
}
}
else if (name == "Qty")
{
if (this._Qty > this._AvailableQty)
{
result = "Qty must be less than Available Qty . Avaialble Qty : " + this._AvailableQty;
}
}
return result;
}
}
#endregion
#region INotifyPropertyChanged Members
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
//// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
I don't clear understand why you want to do so but as example you can enumerate rows and call Validate method on your own like this:
private void Save_Click(object sender, RoutedEventArgs e) {
// create validation object
RowDataInfoValidationRule rule = new RowDataInfoValidationRule();
StringBuilder builder = new StringBuilder();
// enumerate all rows
for (int i = 0; i < dgReceiveInventory.Items.Count; i++) {
DataGridRow row = (DataGridRow) dgReceiveInventory.ItemContainerGenerator.ContainerFromIndex(i);
// validate rule
ValidationResult res = rule.Validate(row.BindingGroup, null);
if (!res.IsValid) {
// collect errors
builder.Append(res.ErrorContent);
}
}
//show message box
MessageBox.Show(builder.ToString());
}
If you have
<DataGrid>
<DataGrid.RowValidationRules>
<local:RowDataInfoValidationRule ValidationStep="UpdatedValue" />
</DataGrid.RowValidationRules>
...
You could use Validation.Error Attached Event
<Window Validation.Error="Window_Error">
to save all validation errors for bindings with NotifyOnValidationError set to true
Text="{Binding ProductName, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
in a List
public List<ValidationError> ValidationErrors = new List<ValidationError>();
private void Window_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
ValidationErrors.Add(e.Error);
else
ValidationErrors.Remove(e.Error);
}
and then show the list entries in a MessageBox in save button click handler.
I have a class to store data:
public enum ColumnType
{
...
}
public class LogColumn
{
public string Name { get; set; }
public ColumnType Type { get; set; }
public bool OrderBy { get; set; }
}
and a ObservableCollection of it in my UserControl:
private ObservableCollection<LogColumn> _logColumns = new ObservableCollection<LogColumn>();
public ObservableCollection<LogColumn> LogColumns
{
get { return _logColumns; }
set
{
_logColumns = value;
OnPropertyChanged("LogColumns");
}
}
This collection is bound to a DataGrid:
<DataGrid Name="dgColumnSelection"
ItemsSource="{Binding LogColumns, UpdateSourceTrigger=LostFocus, Mode=TwoWay, ValidatesOnDataErrors=True}" CanUserAddRows="False" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" IsReadOnly="True" Binding="{Binding Name, UpdateSourceTrigger=LostFocus, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<DataGridComboBoxColumn Header="Type" ItemsSource="{Binding Source={StaticResource ColumnType}}" SelectedValueBinding="{Binding Type, UpdateSourceTrigger=LostFocus, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<DataGridCheckBoxColumn Header="Order by" Binding="{Binding OrderBy, UpdateSourceTrigger=LostFocus, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</DataGrid.Columns>
</DataGrid>
But neither PropertyChanged-event nor Validation is fired. Where is my fault?
Thx.
Best regards
The event is never fired because you are never setting the LogColumns variable to something new. What you are doing is changing properties on the LogColumn items contained within the LogColumns collection.
Implementing the INotifyPropertyChanged interface on your LogColumn class will might help do what you want.
ObservableCollection only notify if the items of ObservableCollection get chagned not the items item get changed to do so you need to implement the inotifyproprty chagned in your logcolumns class
as
public class LogColumn : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; Onchanged("Name"); }
}
private ColumnType _Type;
public ColumnType Type
{
get { return _Type; }
set { _Type = value; Onchanged("Type"); }
}
private bool _OrderBy;
public bool OrderBy
{
get { return _OrderBy; }
set { _OrderBy = value; Onchanged("OrderBy"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void Onchanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
now this will work.