WPF (MVVM) обновление всего DataGrid
Есть программа, которая должна выводить некоторые данные в виде таблицы (DataGrid). Т.к. данных планируется много и все они будут зависеть друг от друга, решил использовать MVVM. Так же, чтобы не реализовывать INotifyPropertyChanged и ICommand, подключил Prism.
Есть класс Line, который представляет из себя набор строк:
public class Line
{
public string ?number { get; set; }
public string ?type { get; set; }
public string ?radius { get; set; }
public string ?tickness { get; set; }
}
В модели все данные хранятся в ObservableCollection _lines. По умолчанию там уже есть одна пустая строка. Для взаимодействия с ViewModel ссылку на _lines хранит ReadOnlyObservableCollection lines.
public class M1Model : BindableBase
{
public readonly ReadOnlyObservableCollection<Line> lines;
public M1Model()
{
lines = new ReadOnlyObservableCollection<Line>(_lines);
}
private ObservableCollection<Line> _lines = new ObservableCollection<Line>()
{
new Line() {}
};
// Добавление строки
public void AddRow(int index)
{
_lines.Add(new Line());
for (int i = 0; i < _lines.Count; i++)
{
_lines[i].number = i.ToString();
}
}
public void RemoveRow(int index)
{
if (_lines.Count > 1)
{
_lines.RemoveAt(index);
}
}
}
В ViewModel для работы с _lines есть ReadOnlyObservableCollection allLines.
public class M1VM : BindableBase
{
M1Model _model = new M1Model();
private string _number;
private string _radius;
private string _tickness;
public ReadOnlyObservableCollection<Line> allLines => _model.lines;
public DelegateCommand<int?> AddRow { get; }
public DelegateCommand<int?> RemoveRow { get; }
public M1VM()
{
_model.PropertyChanged += (s, e) => { RaisePropertyChanged(e.PropertyName); };
AddRow = new DelegateCommand<int?>(i => { if (i.HasValue) _model.AddRow(i.Value); });
RemoveRow = new DelegateCommand<int?>(i => { if (i.HasValue) _model.RemoveRow(i.Value); });
}
public string number
{
get => _number;
set
{
_number = value;
RaisePropertyChanged();
}
}
public string radius
{
get => _radius;
set
{
_radius = value;
RaisePropertyChanged();
}
}
public string tickness
{
get => _tickness;
set
{
_tickness = value;
RaisePropertyChanged();
}
}
}
По личным нуждам всю логику прописывал не для окна, а для Control. Вот его XAML
<UserControl ...>
<UserControl.DataContext>
<local:M1VM/>
</UserControl.DataContext>
<Grid >
<DataGrid x:Name="dataGrid" ItemsSource="{Binding allLines}" AutoGenerateColumns="False">
<DataGrid.InputBindings>
<KeyBinding Key="Insert" Command="{Binding AddRow}" CommandParameter="{Binding ElementName=dataGrid, Path=SelectedIndex}"/>
<KeyBinding Key="Delete" Command="{Binding RemoveRow}" CommandParameter="{Binding ElementName=dataGrid, Path=SelectedIndex}"/>
</DataGrid.InputBindings>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="False" Header="№" Width="40" TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
<DataGridTextColumn Binding="{Binding type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Header="Тип поверхности" Width="110" TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
<DataGridTextColumn Binding="{Binding radius, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Радиус" Width="*" TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
<DataGridTextColumn Binding="{Binding tickness, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Толщина" Width="*" TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
<DataGridTextColumn Header="Оптическая сила" Width="*" TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
Проблема заключается в следующем: когда я добавляю новую строку через метод AddRow у меня обновляется нумерация всех строк (свойство number). Т.е. в первом столбце первой строки должен появится 0, во второй строке - 1. Но, во второй строке единица есть, а вот первая ячейка не обновляется до тех пор, пока ты ее не выделишь двойным кликом.
Мне кажется, проблема заключается в том, что при обновлении коллекции не происходит обновления строк. А PropertyChanged обновляет только конкретную ячейку (свойство). Но как обновить целиком DataGrid я так и не смог разобраться.
Ответы (1 шт):
Мне кажется, проблема заключается в том, что при обновлении коллекции не происходит обновления строк
ObservableCollection, как и ReadOnlyObservableCollection сообщают только об изменении самой коллекции, то есть о том были ли добавлены в коллекцию новые элементы или были ли какие-либо элементы удалены. Об изменениях свойств самих элементов они не сообщают.
Для оповещения об изменении значения в ячейке DataGrid Вам нужно реализовать INotifyPropertyChanged в классе Line. Ну или создать класс LineViewModel: BindableBase, чтобы не загромождать класс модели.
P.S. Свойства number, radius и tickness класса M1VM у Вас не используются. Привязка ячеек DataGrid происходит к элементам коллекции allLines: классу Line.