none
c# wpf datagrid: удаление выделенных строк, обновление и прочие функции RRS feed

  • Вопрос

  • Здравствуйте форумчане!

    Использую c#, wpf, DataGrid, SqlDataAdapter, DataTable, MS Sql server

    Есть форма:

    Для неё не могу реализовать: 1) удаление выделенных в DataGrid строк как через кнопку, так и через горячую клавишу Delete (метод Button_DeleteSelectedMark_Click), 2) обновление строк DataGrid, если в фокусе находится основная форма и нажата клавиша F5 (метод Window_Marks_PreviewKeyDown), 3) так же интересует реализация вставки, удаления (уже писал выше), изменения строк клавишами (горячими) из самой DataGrid (т.е. без использования дополнительных кнопок на форме как у меня).

    Буду признателен, если подскажите какие события надо отлавливать при работе с DataGrid. Еще сомнения вызывает правильность реализации "Удалить все", может есть другой метод, не такой грубый ) Ну и так же принимаются советы по улучшению кода, критика.

    Наработки прилагаю ниже:

    XAML разметка формы:

    <Window x:Class="MyAuto.Painting.Windows.Window_Marks"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:MyAuto.Painting.Windows"
            mc:Ignorable="d"
            Title="Марки автомобилей" 
            Height="610" Width="400">
    
        <Grid>
            <!-- Фильтр -->
            <Label x:Name="label" Content="Фильтрация: " HorizontalAlignment="Left" Margin="10,10,00,0" VerticalAlignment="Top"/>
            <TextBox x:Name="textBox_Filter" HorizontalAlignment="Stretch" Height="23" Margin="111,13,10,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
    
            <!-- Таблица для отображения марок автомобилей -->
            <DataGrid x:Name="dataGrid_Marks"
                      ItemsSource="{Binding dataTable}"
                      Margin="10,50,10,120"  
                      HorizontalAlignment="Stretch" 
                      AutoGenerateColumns="False" 
                      AlternatingRowBackground="#FFC4B0B0" 
                      CanUserAddRows="True" 
                      CanUserDeleteRows="True" 
                      CanUserSortColumns="True">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Марка автомобиля" Binding="{Binding Name}"/>
                </DataGrid.Columns>
            </DataGrid>
    
            <!-- Поле для ввода имени марки автомобиля -->
            <Label x:Name="label_Mark" Content="Марка:" HorizontalAlignment="Left" Margin="10,495,0,0" VerticalAlignment="Top"/>
            <TextBox x:Name="textBox_MarkName" HorizontalAlignment="Stretch" Height="23" Margin="70,498,10,0" TextWrapping="NoWrap" VerticalAlignment="Top"/>
    
            <!-- Кнопки управления списком марок автомобилей -->
            <Button x:Name="button_SelectAll" Content="Выделить всё" HorizontalAlignment="Left" Margin="10,455,0,0" VerticalAlignment="Top" Width="180"/>
            <Button x:Name="button_UnSelectAll" Content="Снять выделение" HorizontalAlignment="Left" Margin="195,455,0,0" VerticalAlignment="Top" Width="187"/>
            <Button x:Name="button_AddMark" Content="Добавить" HorizontalAlignment="Left" Margin="10,538,0,0" VerticalAlignment="Top" Width="63"/>
            <Button x:Name="button_DeleteMark" Content="Удалить" HorizontalAlignment="Left" Margin="86,538,0,0" VerticalAlignment="Top" Width="60"/>
            <Button x:Name="button_DeleteSelectedMark" Content="Удалить выделенные" HorizontalAlignment="Left" Margin="159,538,0,0" VerticalAlignment="Top" Width="126"/>
            <Button x:Name="button_DeleteAllMark" Content="Удалить всё" HorizontalAlignment="Left" Margin="296,538,0,0" VerticalAlignment="Top" Width="86"/>
        </Grid>
    </Window>

    .cs:

    // Подключения по-умолчанию
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    
    // Собственные подключения
    using System.Data.SqlClient;
    using System.Data;
    using System.ComponentModel; // Класс ICollectionView
    
    namespace MyAuto.Painting.Windows
    {
        /// <summary>
        /// Логика взаимодействия для Window_Marks.xaml
        /// </summary>
        public partial class Window_Marks : Window
        {
            private SqlConnection sqlConnection;
            private DataTable dataTable;
            private SqlDataAdapter dataAdapter;
    
            public Window_Marks()
            {
                InitializeComponent();          // Инициализация компонент
                InitializeSqlConnection();      // Инициализация sql-соединения с БД
                InitializeDataTable();          // Инициализация DataTable
                InitializeSqlDataAdapter();     // Инициализация SqlDataAdapter
    
                // События формы
                this.Loaded += Window_Marks_Loaded;
                this.PreviewKeyDown += Window_Marks_PreviewKeyDown;
    
                // События DataGrid
                dataGrid_Marks.SelectionChanged += DataGrid_Marks_SelectionChanged;
                dataGrid_Marks.RowEditEnding += DataGrid_Marks_RowEditEnding;
                dataGrid_Marks.PreviewKeyDown += DataGrid_Marks_PreviewKeyDown;
                
                // События поля "Фильтр"
                textBox_Filter.TextChanged += TextBox_Filter_TextChanged;
    
                // События кнопок
                button_SelectAll.Click += Button_SelectAll_Click;
                button_UnSelectAll.Click += Button_UnSelectAll_Click; 
                button_AddMark.Click += Button_AddMark_Click;
                button_DeleteMark.Click += Button_DeleteMark_Click;
                button_DeleteSelectedMark.Click += Button_DeleteSelectedMark_Click;  
                button_DeleteAllMark.Click += Button_DeleteAllMark_Click;
    
            } // Конец конструктора
     
            #region Инициализация
    
            /// <summary>
            /// Инициализирует sql-соединение
            /// </summary>
            private void InitializeSqlConnection()
            {
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
                builder.DataSource = @"server";                 // Имя SQL-сервера
                builder.InitialCatalog = "MyBase";     	    // Имя БД 
                builder.IntegratedSecurity = true;              // Проверка безопасности подключения средствами Windows
                builder.Pooling = false;                        // При закрытии соединения не помещаем его в пул 
    
                sqlConnection = new SqlConnection();
                sqlConnection.ConnectionString = builder.ToString();
            } // Конец функции InitializeSqlConnection
    
            /// <summary>
            /// Инициализирует DataTable
            /// </summary>
            private void InitializeDataTable()
            {
                dataTable = new DataTable();
            } // Конец функции InitializeDataTable
    
            /// <summary>
            /// Инициализирует SqlDataAdapter
            /// </summary>
            private void InitializeSqlDataAdapter()
            {
                dataAdapter = new SqlDataAdapter();
    
                try
                {
                    // Команда выборки записей
                    dataAdapter.SelectCommand = new SqlCommand();
                    dataAdapter.SelectCommand.Connection = sqlConnection;
                    dataAdapter.SelectCommand.CommandType = CommandType.Text;
                    dataAdapter.SelectCommand.CommandText = @"SELECT DISTINCT Name FROM tb_auto_mark";
    
                    // Команда вставки записей
                    dataAdapter.InsertCommand = new SqlCommand();
                    dataAdapter.InsertCommand.Connection = sqlConnection;
                    dataAdapter.InsertCommand.CommandType = CommandType.Text;
                    dataAdapter.InsertCommand.CommandText = @"INSERT INTO tb_auto_mark(Name) VALUES (@MarkName)";
                    dataAdapter.InsertCommand.Parameters.Add("@MarkName", SqlDbType.NVarChar, 4000, "Name");
    
                    // Команда удаления записей
                    dataAdapter.DeleteCommand = new SqlCommand();
                    dataAdapter.DeleteCommand.Connection = sqlConnection;
                    dataAdapter.DeleteCommand.CommandType = CommandType.Text;
                    dataAdapter.DeleteCommand.CommandText = @"DELETE FROM tb_auto_mark WHERE Name = @MarkName";
                    dataAdapter.DeleteCommand.Parameters.Add("@MarkName", SqlDbType.NVarChar, 4000, "Name");
    
                    // Команда обновления записей
                    dataAdapter.UpdateCommand = new SqlCommand();
                    dataAdapter.UpdateCommand.Connection = sqlConnection;
                    dataAdapter.UpdateCommand.CommandType = CommandType.Text;
                    dataAdapter.UpdateCommand.CommandText = @"UPDATE tb_auto_mark SET Name = @MarkName WHERE Name = @MarkName";
                    dataAdapter.UpdateCommand.Parameters.Add("@MarkName", SqlDbType.NVarChar, 4000, "Name");
    
                    if (dataTable != null)
                        dataAdapter.Update(dataTable); // Обновляем таблицу DataTable
                }
                catch (Exception ex) // Ошибка
                {
                    MessageBox.Show("Ошибка в функции InitializeSqlDataAdapter!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK,  MessageBoxImage.Error);
                }
            } // Конец функции InitializeSqlDataAdapter
    
            #endregion
    
            #region Форма
    
            private void Window_Marks_Loaded(object sender, RoutedEventArgs e)
            {
                dataAdapter.Fill(dataTable);
                dataGrid_Marks.ItemsSource = dataTable.DefaultView;
            } // Конец функции Window_Marks_Loaded
    
            private void Window_Marks_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.F5)
                {
                    dataAdapter.Fill(dataTable);
                    dataGrid_Marks.ItemsSource = dataTable.DefaultView;
                }
            }
    
            #endregion
    
            #region Таблица с данными
            private void DataGrid_Marks_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                // DataRow row = dataGrid_Marks.SelectedItem as DataRow;
            }
    
            private void DataGrid_Marks_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
            {
                /*        try
                        {
                            var Res = MessageBox.Show("Добавить новую марку автомобиля в список?", "Подтверждение", MessageBoxButton.YesNo, MessageBoxImage.Question);
    
                            if (Res == MessageBoxResult.Yes)
                                InsertRow(conn, "INSERT INTO tb_auto_mark (Name) VALUES (111)");
                        }
                        catch (Exception ex)
                        { MessageBox.Show("Ошибка DataGrid_Marks_RowEditEnding " + ex.Message); }*/
            }
    
            private void DataGrid_Marks_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.Key == Key.Delete)
                    {
                        DataGrid grid = sender as DataGrid;
    
                        if (grid.SelectedItems.Count > 0)
                        {
                            foreach (DataRowView item in grid.SelectedItems)
                            {                         
                               // Тут должен быть код по удалению выбранных строк
                            }
                            dataAdapter.Update(dataTable);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции DataGrid_Marks_PreviewKeyDown!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
    
            #endregion
    
            #region Кнопки
    
            private void Button_SelectAll_Click(object sender, RoutedEventArgs e)
            {
                dataGrid_Marks.SelectAll();
            }
    
            private void Button_UnSelectAll_Click(object sender, RoutedEventArgs e)
            {
                dataGrid_Marks.UnselectAll();
            }
    
            private void Button_AddMark_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    if (!string.IsNullOrWhiteSpace(textBox_MarkName.Text)) // Если поле "Марка" не пустое, null или не пробел
                    {
                        var rows = dataTable.Select().Where(r => r["Name"].ToString() == textBox_MarkName.Text);
    
                        if (rows.Count() == 0) // Если значения нет в DataTable - добавляем его туда
                        {
                            DataRow row = dataTable.NewRow();
                            row["Name"] = textBox_MarkName.Text;
                            dataTable.Rows.Add(row);
    
                            dataAdapter.Update(dataTable);
    
                            // Сортируем визуальную таблицу с данными
                           ICollectionView cvs = CollectionViewSource.GetDefaultView(dataGrid_Marks.ItemsSource);
                            if (cvs != null && cvs.CanSort == true)
                            {
                                cvs.SortDescriptions.Clear();
                                cvs.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
                            }
                        }
                        else
                            MessageBox.Show("Марка с названием \"" + textBox_MarkName.Text + "\" уже присутствует в базе данных! Воспользуйтесь фильтром для поиска", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
    
                        textBox_MarkName.Clear();
                        textBox_MarkName.Focus();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_AddMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            } // Конец функции Button_AddMark_Click
    
            private void Button_DeleteMark_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    if (!string.IsNullOrWhiteSpace(textBox_MarkName.Text)) // Если поле "Марка" не пустое, null или не пробел
                    {
                        var rows = dataTable.Select().Where(r => r["Name"].ToString() == textBox_MarkName.Text);
    
                        if (rows.Count() > 0) // Если значение есть в DataTable - удаляем его туда
                        {
                            foreach (DataRow row in dataTable.Rows)
                            {
                                if (row["Name"].ToString() == textBox_MarkName.Text)
                                    row.Delete(); // Помечаем строку на удаление
                            }
    
                            dataTable.AcceptChanges(); // Фиксируем изменения внесенные в DataTable
    
                            dataAdapter.Update(dataTable);
    
                            // Сортируем визуальную таблицу с данными
                            ICollectionView cvs = CollectionViewSource.GetDefaultView(dataGrid_Marks.ItemsSource);
                            if (cvs != null && cvs.CanSort == true)
                            {
                                cvs.SortDescriptions.Clear();
                                cvs.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
                            }
                        }
                        else
                            MessageBox.Show("Марка с названием \"" + textBox_MarkName.Text + "\" нет в базе данных! Воспользуйтесь фильтром для поиска", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
    
                        textBox_MarkName.Clear();
                        textBox_MarkName.Focus();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_DeleteMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            } // Конец функции Button_DeleteMark_Click
    
            private void Button_DeleteSelectedMark_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    if (dataGrid_Marks.SelectedItems.Count > 0)
                    {
                        // Тут должен размещаться код по удалению из DataTable выделенных элементов в DataGrid
    
                        for (int i = dataGrid_Marks.SelectedItems.Count -1; i >=0 ; i--)
                        {
                            DataRowView rowView = dataGrid_Marks.SelectedItems[i] as DataRowView;
    
                            foreach (DataRow row in dataTable.Rows)
                            {
                                if (row["Name"].ToString() == rowView.Row["Name"].ToString())
                                    row.Delete(); // Помечаем строку на удаление
                            }
                        }
                        dataTable.AcceptChanges(); // Фиксируем изменения внесенные в DataTable
                        dataAdapter.Update(dataTable);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_DeleteSelectedMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            } // Конец функции Button_DeleteSelectedMark_Click
    
            private void Button_DeleteAllMark_Click(object sender, RoutedEventArgs e)
            {
                try
                { 
                    if (dataTable != null && dataTable.Rows.Count > 0)
                    {
                        MessageBoxResult res = MessageBox.Show("Вы точно хотите удалить все марки автомобилей из списка?", "Предупреждение", MessageBoxButton.YesNo, MessageBoxImage.Warning);
    
                        if (res == MessageBoxResult.Yes)
                        {
                            // Обычной командой очищаем таблицу в БД
                            using (SqlCommand cmd = new SqlCommand())
                            {
                                cmd.Connection = sqlConnection;
                                cmd.CommandText = "DELETE FROM tb_auto_mark";
    
                                cmd.Connection.Open();
                                cmd.ExecuteNonQuery();
                                cmd.Connection.Close();
                            }
    
                            dataTable.Rows.Clear(); // Через очистку DataTable очищаем представление от старых данных
                            dataAdapter.Fill(dataTable); // "Синхронизируем" пустую таблицу в БД и DataTable
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_DeleteAllMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                textBox_MarkName.Focus();
            } // Конец функции Button_DeleteAllMark_Click
    
            #endregion
    
            private void TextBox_Filter_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (dataTable != null && dataTable.Rows.Count > 0)
                {
                    /*   string filter = string.Format("Name LIKE '%{0}%'", textBox_Filter.Text);
                       dataTable.DefaultView.RowFilter = filter;
    
                       dataGrid_Marks.ItemsSource = dataTable.DefaultView;
                     }*/
    
                    /*DataView view = new DataView(dataTable);
                    view.RowFilter = string.Format("Name LIKE '%{0}%'", textBox_Filter.Text);
                    dataGrid_Marks.ItemsSource = view;*/
                }
            }
    
          
            
        }
    }
    Спасибо!



    • Изменено kremlinbot 15 мая 2016 г. 16:01 уточнения

Ответы

  • Нет, вы не правильно понимаете. Один топик - один вопрос. Если вы одно сообщение разбили на несколько маленьких, но их объем в одном топике не уменьшился... У меня есть сомнение, что кто-то будет это все разбирать...

    Складывается тенденция: раньше приходилось новичку разжевывать решение и в рот класть код, то профессиональное общество настолько деградировало, что теперь спрашивающий новичок должен разжевать свои вопросы для гуру :D:D:D 

    Вопрос №1 (удаление нескольких выделенных строк DataGrid) решен:

    private void Button_DeleteSelectedRows_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (dataGrid.SelectedItems.Count == 1)
                {
                    int selectedIndex = dataGrid.SelectedIndex;
                    var row = dataTable.Rows[selectedIndex];
                    row.Delete();
    
                    dataAdapter.Update(dataTable);
                }
                else if (dataGrid.SelectedItems.Count > 1)
                {
                    while (dataGrid.SelectedItems.Count > 0)
                    {
                        int selectedIndex = dataGrid.SelectedIndex;
                        var row = dataTable.Rows[selectedIndex];
                        row.Delete();
    
                        dataAdapter.Update(dataTable);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
    }


    3 июня 2016 г. 22:47

Все ответы

  • Добрый день.

    Это форум, здесь дают конкретные ответы, на конкретные вопросы. Когда вы вываливаете десять экранов кода и вопросы типа: "все не работает", в большинстве случает, остаются без ответа.

    Подготовьте маленький примерчик на каждый вопрос. По каждому напишите что у вас получается, а что нет. Задайте конкретный вопрос. Сейчас надо программу написать за вас...

    Ну и в 2016 году от рождества христова неплохо бы разобраться что такое MVVM, Entity Framework. Узнав что это такое, вы разработку приложений на WPF использующих базы данных себе существенно облегчите.


    Отвечающий
  • Алексей, спасибо за отзыв. Разобью свой пост на несколько отдельных вопросов.

    Вопрос 1. Удаление выделенных строк в DataGrid

    На форме вы видите кнопки связанные с удалением: удалить, удалить выделенное, удалить всё.

    На данный момент не получается реализовать кнопку "Удалить выделенное". Вот обработчик нажатия на кнопку:

     private void Button_DeleteSelectedMark_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    if (dataGrid_Marks.SelectedItems.Count > 0)
                    {
                        for (int i = dataGrid_Marks.SelectedItems.Count -1; i >=0 ; i--)
                        {
                            DataRowView rowView = dataGrid_Marks.SelectedItems[i] as DataRowView;
    
                            foreach (DataRow row in dataTable.Rows)
                            {
                                if (row["Name"].ToString() == rowView.Row["Name"].ToString())
                                    row.Delete(); // Помечаем строку на удаление
                            }
                        }
                        dataTable.AcceptChanges(); // Фиксируем изменения внесенные в DataTable
                        dataAdapter.Update(dataTable);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_DeleteSelectedMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            } // Конец функции Button_DeleteSelectedMark_Click

    Немного о коде:

    - получаем выделенные строки в DataGrid;

    - далее сравниваю названия выделенных марок в DataGrid с имеющимися записями в DataTable и помечаю их на удаление

    - фиксируем изменения, при которых происходит удаление строк

    - обновляем с помощью DataAdaptera строки в БД

    Возникает ошибка: Невозможно получить доступ к удаленной информации строки через данную строку.

    Данная ошибка возникает после окончания цикла for и минуя выполнение строк

    dataTable.AcceptChanges(); // Фиксируем изменения внесенные в DataTable
    dataAdapter.Update(dataTable);

    Сразу возникает исключение из-за того, что в DataTable помечены строки на удаление. Проверка их состояния типа row.RowState != DataRowState.Deleted перед проверкой 

     if (row["Name"].ToString() == rowView.Row["Name"].ToString())

    Не помогает.

    В общем так тоже не работает:

    foreach (DataRow row in dataTable.Rows) {

    if (row.RowState != DataRowState.Deleted || row.RowState != DataRowState.Detached)

    { if (row["Name", DataRowVersion.Original].ToString() == rowView.Row["Name"].ToString()) row.Delete(); // Помечаем строку на удаление

    } }

  • Вопрос 2. Удаление строки из DataGrid "горячей клавишей" Delete

    private void DataGrid_Marks_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.Key == Key.Delete)
                    {
                        DataGrid grid = sender as DataGrid;
    
                        if (grid.SelectedItems.Count > 0)
                        {
                            foreach (DataRowView item in grid.SelectedItems)
                            {                         
                               // Тут должен быть код по удалению выбранных строк
                            }
                            dataAdapter.Update(dataTable);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции DataGrid_Marks_PreviewKeyDown!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

    Реализация метода не закончена, поскольку не решен вопрос №1. Решение я думаю будет то же самое.

    Здесь меня больше интересует другое. Правильное ли событие я отслеживаю?

    Почему, если мой метод не рабочий, из DataGrid все равно удаляется строка при нажатии Delete. Т.е. какой бы мой код не был нерабочим, чтобы я не назначал на клавишу Delete, все равно сначала происходит удаление строки из интерфейса DataGrid (естественно изменений в БД нет, т.к. DataTable не изменена). Почему? DataGrid жестко подписан на команду связанную с клавишей Delete? Например, я захочу, чтобы при нажатии на Delete не происходило удаление из визуальной части, а всего лишь показывалось сообщение. Или мне надо удаление клавишей не Delete, а Ctrl+Delete. Как быть?

  • Вопрос 3. Удаление всех строк из DataGrid (работа кнопки "Удалить всё"). 

    Ниже представлена реализация.

    private void Button_DeleteAllMark_Click(object sender, RoutedEventArgs e)
            {
                try
                { 
                    if (dataTable != null && dataTable.Rows.Count > 0)
                    {
                        MessageBoxResult res = MessageBox.Show("Вы точно хотите удалить все марки автомобилей из списка?", "Предупреждение", MessageBoxButton.YesNo, MessageBoxImage.Warning);
    
                        if (res == MessageBoxResult.Yes)
                        {
                            // Обычной командой очищаем таблицу в БД
                            using (SqlCommand cmd = new SqlCommand())
                            {
                                cmd.Connection = sqlConnection;
                                cmd.CommandText = "DELETE FROM tb_auto_mark";
    
                                cmd.Connection.Open();
                                cmd.ExecuteNonQuery();
                                cmd.Connection.Close();
                            }
    
                            dataTable.Rows.Clear(); // Через очистку DataTable очищаем представление от старых данных
                            dataAdapter.Fill(dataTable); // "Синхронизируем" пустую таблицу в БД и DataTable
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ошибка в функции Button_DeleteAllMark_Click!\n\n" + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                textBox_MarkName.Focus();
            } // Конец функции Button_DeleteAllMark_Click

    В данном обработчике, я напрямую очищаю таблицу БД sql-командой DELETE FROM, а потом заново заливаю DataTable пустыми значениями из БД. Насколько корректно данное решение?

    Попытки удалить все строки, как dataTable.Rows.Clear() или dataTable.Clear() не увенчиваются успехом. DataTable очищается, очищается DataGrid, но таблица в БД не очищается. Т.к. всего скорее DataAdapter не знает как это сделать. Ему не прописана команда DELETE FROM table_name. 

    Стоит ли DataAdapter'у переопределять в данном методе на время команду DeleteCommand?

    Так удалить все строки тоже не получается:

     foreach (DataRow row in dataTable.Rows)
     {
             row.Delete(); // Помечаем строку на удаление
      }
     dataTable.AcceptChanges(); // Фиксируем изменения внесенные в DataTable
     dataAdapter.Update(dataTable);

  • Вопрос 4. Обновление (изменение) значения ячейки в DataGrid.

    Здесь я вообще не понимаю механизм обновления...

    Код:

    private void DataGrid_Marks_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                MessageBox.Show("CellEditEnding");
            }
    
    private void DataGrid_Marks_RowEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                MessageBox.Show("RowEditEnding");
            }

    Допустим имеем список марок, как на первом скриншоте в начале темы. Начинаем редактировать строку со значением "1". Сначала вызывается CellEditEnding, потом RowEditEnding, потом идет выделение строки со значением "2". Что за поведение?! Почему не остались в измененной строке с бывшим значением "1", а сместились на строку ниже?

    Если начать редактировать ячейки "1", "2" и т.д., то в textBox попадает полная ерунда..

       private void DataGrid_Marks_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                DataRowView rowView = e.Row.Item as DataRowView;
                textBox_MarkName.Text = rowView["Name"].ToString();
            }

    Еще вопрос, как зафиксировать изменения dataTable, после изменения значения ячейки в DataGrid?

  • Добрый день.

    Ну и в 2016 году от рождества христова неплохо бы разобраться что такое MVVM, Entity Framework. Узнав что это такое, вы разработку приложений на WPF использующих базы данных себе существенно облегчите.


    Алексей, спасибо за совет. Я смотрел в сторону этих технологий, но решил, что пока не смогу освоить базовые элементы типа SqlDataAdapter, SqldataReader, DataTable, DataGrid, вызов SQL команд, хранимых процедур в обычном приложении WPF - нет смысла изучать какие-либо новейшие технологии, выстраивать красивую архитектуру приложения, если я не смогу просто изменить значение в ячейке DataGrid -(( Пока мне нужен базис :) Как только его освою - буду пытаться переделать это приложение на MVVC, EF.

  • Я правильно понимаю, что на официальном форуме microsoft нет ни одного разработчика, который бы реализовал, например, удаление выбранных строк из DataGrid в связке с DataTable? :> shame. Видимо все приличные программисты и кодеры сгинули вместе с GotDotNet.

  • Нет, вы не правильно понимаете. Один топик - один вопрос. Если вы одно сообщение разбили на несколько маленьких, но их объем в одном топике не уменьшился... У меня есть сомнение, что кто-то будет это все разбирать...
    Отвечающий
  • Нет, вы не правильно понимаете. Один топик - один вопрос. Если вы одно сообщение разбили на несколько маленьких, но их объем в одном топике не уменьшился... У меня есть сомнение, что кто-то будет это все разбирать...

    Складывается тенденция: раньше приходилось новичку разжевывать решение и в рот класть код, то профессиональное общество настолько деградировало, что теперь спрашивающий новичок должен разжевать свои вопросы для гуру :D:D:D 

    Вопрос №1 (удаление нескольких выделенных строк DataGrid) решен:

    private void Button_DeleteSelectedRows_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (dataGrid.SelectedItems.Count == 1)
                {
                    int selectedIndex = dataGrid.SelectedIndex;
                    var row = dataTable.Rows[selectedIndex];
                    row.Delete();
    
                    dataAdapter.Update(dataTable);
                }
                else if (dataGrid.SelectedItems.Count > 1)
                {
                    while (dataGrid.SelectedItems.Count > 0)
                    {
                        int selectedIndex = dataGrid.SelectedIndex;
                        var row = dataTable.Rows[selectedIndex];
                        row.Delete();
    
                        dataAdapter.Update(dataTable);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
    }


    3 июня 2016 г. 22:47
  • Вопрос №3 - также решен. Оба вопроса (1 и 3) - взаимосвязаны (удаление выделенных строк).
    3 июня 2016 г. 22:50
  • Складывается тенденция: раньше приходилось новичку разжевывать решение и в рот класть код, то профессиональное общество настолько деградировало, что теперь спрашивающий новичок должен разжевать свои вопросы для гуру :D:D:D 

    Не знаю как с GotDotNet, может там и были желающие тратить кучу времени на разбор банальных вопросов, а тут таких нет. На самом деле большинство ответов здесь сводятся к указанию ссылки на статью в MSDN, которую вопрошающий сам поленился найти. Интересные вопросы встречаются крайне редко.

    Вот и у вас вопрос не столь интересный что бы тратить на него время. Вы говорите о работе со строками DataGrid, но это не правильно. Работать нужно с базой данных, а DataGrid будет всего лишь реагировать на эту работу. Правильно задав вопрос можно получить правильный ответ.

    Впрочем чуть погодя вы до этого сами дошли. Выходит и гуру не так нужны, если не поленится и поискать ответ самостоятельно. Например в поиске по этому форуму можно найти с 50 вопросов на тему работы с базами данных.


    VB.Net - WPF, UWP

    4 июня 2016 г. 15:32
    Отвечающий