У DataGrid после сохранения поля становятся пустыми. Как исправить?
У меня есть элемент DataGrid, с 4 колонками типа ComboBox. Все заполняется отлично, однако после сохранения и переоткрытия окна - поля строк отображаются пустыми.

WPF:
<DataGrid x:Name="datagrid" AutoGenerateColumns="False" ItemsSource="{Binding Items}" SelectionMode="Single" Grid.ColumnSpan="5" Grid.Row="1" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserAddRows="False" RowDetailsVisibilityMode="Visible" SelectedItem="{Binding SelectedItem}" SelectedIndex="{Binding SelectedIndex}" >
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Kind:" Width="25*" SelectedItemBinding="{Binding Kind, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="KindId" DisplayMemberPath="KindName">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding KindItems}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<EventSetter Event="SelectionChanged" Handler="SomeSelectionChanged" />
<Setter Property="ItemsSource" Value="{Binding KindItems}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn Header="Name:" Width="25*" SelectedItemBinding="{Binding Theme, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="FieldId" DisplayMemberPath="FieldName">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding ThemeItems}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding ThemeItems}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn Header="Start:" Width="25*" SelectedItemBinding="{Binding Start, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="FieldId" DisplayMemberPath="FieldName">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding StartItems}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding StartItems}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn Header="End:" Width="25*" SelectedItemBinding="{Binding End, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="FieldId" DisplayMemberPath="FieldName">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding EndItems}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding EndItems}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
C#:
internal partial class CalendarDialog : Window, INotifyPropertyChanged, IComponentConnector
{
private readonly IServiceProvider serviceProvider;
private readonly ICContextProvider contextProvider;
private ICommand addItemCommand;
private ICommand removeItemCommand;
private ICommand okCommand;
private ICommand cancelCommand;
private ICommand cheatCommand;
private ObservableCollection<CalendarMetaItem> items;
private CalendarMetaItem selectedItem;
private List<KindModel> kindItems;
public int SelectedIndex { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public CalendarDialog(IServiceProvider serviceProvider)
{
InitializeComponent();
this.serviceProvider = serviceProvider;
contextProvider = new ServiceHelper(serviceProvider).ContextProvider;
this.Loaded += CalendarDialog_Loaded;
}
private void CalendarDialog_Loaded(object sender, RoutedEventArgs e)
{
this.UpdateLayout();
}
public void Initialize(List<CalendarMetaItem> items)
{
Items = new ObservableCollection<CalendarMetaItem>();
var completeItems = items;
InitKindItems();
foreach (var item in completeItems ?? Enumerable.Empty<CalendarMetaItem>())
{
var fields = InitKindFields(new Guid(item.Kind.TypeId));
Items.Add(new CalendarMetaItem
{
Kind = item?.Kind,
Theme = item?.Theme,
Start = item?.Start,
End = item?.End,
KindItems = new ObservableCollection<KindModel>(kindItems),
ThemeItems = new ObservableCollection<FieldModel>(fields?.StringFields),
StartItems = new ObservableCollection<FieldModel>(fields?.DateFields),
EndItems = new ObservableCollection<FieldModel>(fields?.DateFields)
});
}
UpdateLayout();
}
private void InitKindItems()
{
var context = currentContextProvider.GetContext();
var kindService = context.GetService<IKindService>();
var types = kindService.Kinds.Types;
var allKinds = new List<KindModel>();
foreach (var type in types)
{
if (type.CardTypeId.Equals(CardDocument.ID) || type.CardTypeId.Equals(CardTask.ID))
{
var typeId = type.Id.ToString();
var rootKindId = type.RootKind.Id.ToString();
var rootKindProto = new KindModel();
rootKindProto.TypeId = typeId;
rootKindProto.KindId = rootKindId;
rootKindProto.Level = 0;
rootKindProto.KindName = type.RootKind.Name;
rootKindProto.ParentKindId = Guid.Empty.ToString();
allKinds.Add(rootKindProto);
foreach (var kind in type.Kinds)
{
var level = 2;
var kindProto = new KindModel();
kindProto.TypeId = typeId;
kindProto.Level = 1;
kindProto.KindName = kind.Name;
kindProto.KindId = kind.Id.ToString();
kindProto.ParentKindId = rootKindId;
allKinds.Add(kindProto);
searchR(allKinds, level, kind, typeId);
}
}
}
kindItems = allKinds;
}
private void searchR(List<KindModel> allKinds, int level, KindsCardKind kind, string typeId)
{
if (kind.Kinds.Count > 0)
{
foreach (var k in kind.Kinds)
{
var kindProto = new KindModel();
kindProto.TypeId = typeId;
kindProto.Level = level;
kindProto.KindName = k.Name;
kindProto.KindId = k.Id.ToString();
kindProto.ParentKindId = kind.Id.ToString();
allKinds.Add(kindProto);
level++;
searchR(allKinds, level, k, typeId);
}
}
}
private KindFields InitKindFields (Guid typeId)
{
var context = currentContextProvider.GetContext();
var data = context.GetService<IDataProvider>().GetData(typeId);
var stringFields = new List<FieldModel>();
var dateFields = new List<FieldModel>();
foreach (var table in data.Tables)
{
var sectName = table.Name;
var sectId = table.Id;
foreach (var field in table.Fields)
{
if (field.Type == FieldType.String)
{
var myField = new FieldModel();
myField.SectionName = sectName;
myField.SectionId = sectId.ToString();
myField.FieldName = field.Name;
myField.FieldId = field.Id.ToString();
stringFields.Add(myField);
}
if (field.Type == FieldType.DateTime)
{
var myField = new FieldModel();
myField.SectionName = sectName;
myField.SectionId = sectId.ToString();
myField.FieldName = field.Name;
myField.FieldId = field.Id.ToString();
dateFields.Add(myField);
}
}
}
return new KindFields
{
StringFields = stringFields,
DateFields = dateFields
};
}
public CalendarMetaItem SelectedItem
{
get
{
return this.selectedItem;
}
set
{
SetField(ref this.selectedItem, value);
}
}
public ObservableCollection<CalendarMetaItem> Items
{
get
{
return this.items;
}
set
{
SetField(ref this.items, value, "Items");
}
}
public ICommand AddItemCommand
{
get
{
return this.addItemCommand ?? (this.addItemCommand = new RelayCommand(this.AddItem));
}
}
public ICommand RemoveItemCommand
{
get
{
return this.removeItemCommand ?? (this.removeItemCommand = new RelayCommand(this.RemoveItem, this.CanRemoveItem));
}
}
public ICommand OkCommand
{
get
{
return this.okCommand ?? (this.okCommand = new RelayCommand(this.Ok, this.CanOk));
}
}
public ICommand CancelCommand
{
get
{
return this.cancelCommand ?? (this.cancelCommand = new RelayCommand(this.Cancel));
}
}
public ICommand CheatCommand
{
get
{
return this.cheatCommand ?? (this.cheatCommand = new RelayCommand(this.Cheat));
}
}
private void AddItem()
{
var item = new CalendarMetaItem();
item.KindItems = new ObservableCollection<KindModel>(kindItems);
this.Items.Add(item);
}
private bool CanRemoveItem(object obj)
{
return SelectedItem != null;
}
private void RemoveItem()
{
Items.Remove(SelectedItem);
}
private void Cancel()
{
base.DialogResult = false;
Close();
}
private void Ok()
{
base.DialogResult = true;
Close();
}
private bool CanOk(object obj)
{
return true;
}
private void SomeSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
var item = comboBox.SelectedItem as KindModel;
var fields = InitKindFields(new Guid(item.TypeId));
DataGridRow row = (DataGridRow) datagrid.ContainerFromElement(comboBox);
int rowIndex = row.GetIndex();
Items[rowIndex].ThemeItems = new ObservableCollection<FieldModel>(fields.StringFields);
Items[rowIndex].StartItems = new ObservableCollection<FieldModel>(fields.DateFields);
Items[rowIndex].EndItems = new ObservableCollection<FieldModel>(fields.DateFields);
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
RaisePropertyChanged(propertyName);
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
propertyChanged(this, e);
}
}
private bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
{
return false;
}
field = value;
RaisePropertyChanged(propertyName);
return true;
}
}
Models:
class CalendarMetaItem : INotifyPropertyChanged
{
private KindModel kind;
private FieldModel theme;
private FieldModel start;
private FieldModel end;
public KindModel Kind
{
get
{
return this.kind;
}
set
{
this.kind = value;
NotifyPropertyChanged("Kind");
}
}
[JsonIgnore]
public ObservableCollection<KindModel> KindItems { get; set; }
public FieldModel Theme
{
get
{
return this.theme;
}
set
{
this.theme = value;
NotifyPropertyChanged("Theme");
}
}
[JsonIgnore]
public ObservableCollection<FieldModel> ThemeItems { get; set; }
public FieldModel Start
{
get
{
return this.start;
}
set
{
this.start = value;
NotifyPropertyChanged("Start");
}
}
[JsonIgnore]
public ObservableCollection<FieldModel> StartItems { get; set; }
public FieldModel End
{
get
{
return this.end;
}
set
{
this.end = value;
NotifyPropertyChanged("End");
}
}
[JsonIgnore]
public ObservableCollection<FieldModel> EndItems { get; set; }
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}