Требуется: сделать так что бы это работало как задумано ( с помощью Visual Studio 2015 ).
Затык: После нажатия кнопки «Удалить» строка грида остаётся на месте — не удаляется.
Предупреждение
qw1 дал комент по изложенному материалу:
DataSet плохое решение для WPF-приложения.
И вообще, этот проект архитектурно ужасен — очень много code behind, лучше пользоваться чистым MVVM.
За загрузку данных из БД должен отвечать слой доступа к данным (DAL).
Данные грузятся в ObservableCollection, который назначается как ItemsSource у DataGrid.
Команды манипуляции с данными вызывают DAL для удаления записи из БД и одновременно убирают item из коллекции.
Вывод: Обновление DataGrid описанным в статье способом нельзя, но если очень хочется, то можно — просто испоганите архитектуру приложения.
Начало
Сделал всё по учебнику ( "Пошаговое руководство. Привязка элементов управления WPF к набору данных" ).
И всё работало и было хорошо, пока я не добавил кнопку «DELETE».
meteoStationsReferenceTableAdapter.Delete(recordIndex);
Корень зла
Пошаговое руководство ни чего о кнопке «Удалить» не говорило, её добавление стало причиной всех бед.
Начались странности:
- открываешь приложение
- в DataGrid автоматически подгружается табличка
- нажимаешь кнопку «DELETE»
- а ни чего не происходит!
Если переоткрыть приложение, то да, запись отсутствует — то есть запись была удалена, но DataGrid этого не отрисовал.
Поиск решения
Поискал у DataGrid в методах «Refresh» и на удивление ни чего похожего не нашёл.
Спросил у Гугла «refresh datagrid wpf c#».
Сбросить ItemsSource
1) How to refresh datagrid in WPF
myGrid.ItemsSource = null;
myGrid.ItemsSource = myDataSource;
Присваивания ItemsSource я ни где не писал, и я был без понятия где бы такое могло быть — такой вариант не годился.
<DataGrid x:Name="MeteoStationsReferenceDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="0,52,9.6,10" RowDetailsVisibilityMode="VisibleWhenSelected" CanUserReorderColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="IdColumn" Binding="{Binding id}" Header="id" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="NameColumn" Binding="{Binding name}" Header="name" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="DescriptionColumn" Binding="{Binding description}" Header="description" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
ItemsSource="{Binding}"
ни какого ItemsSource.
Обновить отображение
2) [WPF] Обновление DataGrid
Предлагается два варианта, первый:
this.TransactionsDataGrid.ItemsSource = null;
this.TransactionsDataGrid.ItemsSource = DataProvider.Instance.GetTransactions();
Где у меня DataProvider и что бы это такое могло быть я снова был без понятия.
Второй вариант:
CollectionViewSource.GetDefaultView(TransactionsDataGrid.ItemsSource).Refresh();
Это было уже понятней, я попробовал:
var meteoStationsReferenceDataGrid = this.MeteoStationsReferenceDataGrid;
if (meteoStationsReferenceDataGrid?.ItemsSource != null)
{
var collectionView = CollectionViewSource.GetDefaultView(
meteoStationsReferenceDataGrid.ItemsSource);
collectionView?.Refresh();
}
Ни чего не изменилось — желанного результата не получилось, ок, продолжим поиски.
Сколько я не искал везде был вариант со сбросом и присваиванием ItemsSource. Ещё был вариант с "INotifyPropertyChanged Interface", но для меня это совсем дремучий лес.
Решение
Я продолжал поиски, пока Фортуна не улыбнулась мне, подсунув ссылку [RESOLVED] Refresh DataGridView after adding/deleting records, где было чёрным по белому написано:
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
'----------------------------------------------------------------------------
Dim newRow = DirectCast(ProduseBindingSource.AddNew(), DataRowView)
newRow("pret") = Pret.Text
ProduseBindingSource.EndEdit()
Me.ProduseTableAdapter.Update(Me.Database1DataSet1)
End Sub
И тут до меня доехало, что данные надо перечитать, в смысле залить по новой:
/* Удаляем запись */
meteoStationsReferenceTableAdapter.Delete(recordIndex);
/*
Флаг ClearBeforeFill наверное надо установить на инициализации формы
*/
meteoStationsReferenceTableAdapter.ClearBeforeFill = true ;
var meteoStationsReferenceDataSet = this._meteoStationsReferenceDataSet ;
if ( meteoStationsReferenceDataSet != null )
{
/* читаем данные */
meteoStationsReferenceTableAdapter.Fill
(
meteoStationsReferenceDataSet.meteo_stations_reference ) ;
}
Проверил — получилось.
На мой вкус повторное чтение набора данных это более «цивилизованный» способ чем сброс и установка ItemsSource.
PS
С WPF я так и не подружился.
Исходники на GitHub
Комментарии (15)
semmaxim
11.03.2016 07:36+7Ещё был вариант с «INotifyPropertyChanged Interface», но для меня это совсем дремучий лес.
Вы серьёзно?! Да без данного паттерна к WPF вообще подступать нельзя. В нём всё завязано на PropertyChanged / CollectionChanged. Почему Вы не WinForms взяли?
Genoik
11.03.2016 09:01я бы вам посоветовал прочитать вот тут все внимательно, благо расписано по шагам: http://howtowpf.ru/datagrid-mvvm/
Seekeer
11.03.2016 09:40+1ни где
Скажите, для Вас русский — не родной? Иного объяснения подобным повторяющимся ошибкам я не вижу.
ни чего
ни какого
до меня доехало
Читая подобные темы понимаешь, что Хабр действительно скорее мёртв, чем жив. Особенно учитывая, что статья на главной.SbWereWolf
11.03.2016 09:54-2пишите свои статьи, кто же вам мешает? свято место пусто не бывает, если вы его красотой не можете наполнить, то другие люди заваливают его мусором и грязью.
у меня была проблема которую я решал в течении нескольких часов, и по результатам поиска я видел что я не один такой, поэтому я поделился своим опытом.
Вам есть чем поделиться? Делитесь.
Я к этой статье получил до чёрта минусов, но я рад что моё решение получило квалифицированную оценку, и у следующего человека который будет искать решение — будет масса подсказок.semmaxim
11.03.2016 10:33+3Раз Вы выставили свою статью на всеобщее обозрение — будьте готовы, что её будут обсуждать и даже критиковать.
Тем более Вы совершенно не разобрались в том, что используете. Да ещё и статью написали, в которой не рассказали, как именно надо делать, а рассказали, как делать не надо и как можно это "не надо" подпереть жутким костылём.
Seekeer
11.03.2016 11:39+4у меня была проблема которую я решал в течении нескольких часов
Основная Ваша проблема не в том, что Вы чего-то не знаете, а в том, что не умеете искать. Нормально сформулированный поисковый запрос и вы уже через 5 минут читаете о INotifyCollectionChanged .
я поделился своим опытом.
Хабр это всё-таки не площадка для личных блогов и не любым своим опытом стоит делиться. Как минимум нужно убедиться в правильности того, чем вы хотите поделиться, а ещё лучше — в уникальности.
Ну и прогнать хотя бы через примитивнейшую проверку грамотности.
будет масса подсказок.
Задав вопрос гуглу можно в течении нескольких минут получить намного больше подсказок..
qw1
С этим надо разбираться, нотификации это ключ к правильным интерфейсам без жёстких рефрешей и прочей ереси.
Коллекция, привязанная к DataGrid, должна реализовывать INotifyCollectionChanged.
В качестве DataSource вместо
List<T>
можно взятьObservableCollection<T>
, при вставке/удалении элемента эта коллекция самостоятельно оповещает DataGrid через INotifyCollectionChangedSbWereWolf
доступным для "эникейщиков" языком можно изложить?
Я DataSource ни где ни как не задавал, как я его тип изменю на ObservableCollection ?
звучит волшебно, но как это реализовать?
пример wpf приложения на гите, как в нём применить ваше решение?
leschenko
DataProvider.Instance.GetTransactions(); должен возвращать не просто IList<что-то там>, а ObservableCollection<что-то там>.
SbWereWolf
я писал:
и сейчас я напишу тоже самое:
Где у меня DataProvider и что бы это такое могло быть я без понятия.
Ваши подсказки мне не помогли, но тому кто поумней конечно пригодятся.
qw1
DataSet плохое решение для WPF-приложения.
И вообще, этот проект архитектурно ужасен — очень много code behind, лучше пользоваться чистым MVVM.
За загрузку данных из БД должен отвечать слой доступа к данным (DAL).
Данные грузятся в ObservableCollection, который назначается как ItemsSource у DataGrid.
Команды манипуляции с данными вызывают DAL для удаления записи из БД и одновременно убирают item из коллекции.
SbWereWolf
Так уже понятней. Но в данном случаи не применимо, потому что выполнено всё на автопилоте, без понимания сути действий — всё сделано как Микрософт прописал. Моего там кнопка "Удалить" и "Обновить".
qw1
Наверное, очень старое руководство. Всё сделано в стиле WinForms.
В новом API WinRT, в UWP DataSet больше не поддерживается.
lair
Писать код без понимания сути действий — очень плохая практика.