Имея две коллекции в ViewModel
, одна работает как источник строк для DataGrid
(в этом случае имеют только значения 1,2,3, ..), а другие объект, который представляет секвенсор для одного столбца в DataGrid (на основе идентификатора выставить некоторое значение в свойстве).
В приведенном ниже примере я использовал поведение по умолчанию ObservableObject
и FullyObservableCollection
, но это также было опробовано с другими типами коллекций, но безуспешно. Поведение WPF было протестировано на DataGridComboBoxColumn
и DataGridTemplateColumn
с ComboBox
.
ViewModel:
public class ViewModel : ObservableObject
{
private FullyObservableCollection<Seq> mSequencer;
public FullyObservableCollection<Seq> Sequencer
{
get { return mSequencer; }
set { SetProperty(ref mSequencer, value); }
}
private FullyObservableCollection<RowSrc> mRowSource;
public FullyObservableCollection<RowSrc> RowSource
{
get { return mRowSource; }
set { SetProperty(ref mRowSource, value); }
}
}
Определения классов:
public class Seq : ObservableObject
{
private int mId;
public int Id
{
get { return mId; }
set { SetProperty(ref mId, value); }
}
private string mName;
public string Name
{
get { return mName; }
set { SetProperty(ref mName, value); }
}
}
public class RowSrc : ObservableObject
{
private int mValue;
public int Value
{
get { return this.mValue; }
set { SetProperty(ref mValue, value); }
}
}
Просмотр - XAML:
<CollectionViewSource x:Key="Proxy" Source="{Binding Sequencer}"/>
<DataGrid ItemsSource="{Binding RowSource}">
<DataGrid.Columns>
<DataGridComboBoxColumn
ItemsSource="{Binding Source={StaticResource Proxy}"
SelectedValueBinding="{Binding Value}"
SelectedValuePath="Id"
DisplayMemberPath="Name"/>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
Исходя из вышесказанного, сетка данных инициализируется со значениями RowSource
, которые будут проходить через туннель привязки к Proxy
, что приведет к Sequencer
. Исходя из Value
каждой строки, объект с таким же Id
будет возвращен из коллекции Sequencer
.
Как есть, при первом запуске все работает хорошо. Проблема начинается, когда мы хотим очистить секвенсор и заполнить его снова.
Sequencer.Clear();
Sequencer.AddRange(...);
Теперь элементы в Sequencer
обновляются, однако связь между Row[n].Combobox
и элементами в Sequencer НЕ ОБНОВЛЯЕТСЯ . Причина этого в том, что сами свойства не изменились, только элементы в коллекции.
Обходной путь - взломать:
public class RowSrc
{
...
public void InvokeChange()
{
OnPropertyChanged(nameof(Value));
}
}
public class ViewModel
{
Sequencer.Clear();
Sequencer = GenerateNewCollection();
//after update of Sequencer
foreach (var nRowSrc in RowSrc) nRowSrc.InvokeChange();
}
Однако это означает, что нам нужно будет добавить этот конкретный метод к каждому из наших классов Model, а затем не забывать вызывать их при каждом изменении Sequencer.
В: Как автоматически вызывать изменение свойства при изменении коллекции ИЛИ как правильно обрабатывать эту привязку?