none
DataGridViewについて RRS feed

  • 質問

  • 開発環境

    Visual Studio 2013(Basic)
    windows 10 pro 64bit
    .NET Framework 4.5

    SQLはSQLiteを使用しています。

    2番目の項目を削除すると

    となり、1番目の項目が空白になりまして、、、、

            Dim deletePath As String = Nothing

            ' ------------------------------------------------------
            ' エラーチェック
            ' ------------------------------------------------------
            If name = Nothing Then
                'メッセージボックスを表示する
                MessageBox.Show("削除する項目を選択してください", _
                                "エラー", _
                                MessageBoxButtons.OK, _
                                MessageBoxIcon.Error)
                Exit Sub
            End If

            ' ------------------------------------------------------
            ' SQL 削除処理
            ' ------------------------------------------------------

            Dim dt As DataTable = New DataTable()
            'SQLiteへの接続情報の設定をします。
            Dim builder As SQLiteConnectionStringBuilder = New SQLiteConnectionStringBuilder()

            'SQLiteのファイルへのパスを設定します。
            builder.DataSource = ".\recipe.db"

            '接続情報を使ってコネクションを生成します。
            Using conn As New SQLiteConnection(builder.ConnectionString)

                'オープン
                conn.Open()


                'SQL文とコネクションを設定します。
                Using cmd As New SQLiteCommand("SELECT dir FROM exrecipe where name = @name", conn)
                    'パラメータの作成
                    Dim prmtr1 As SQLiteParameter = New SQLiteParameter()
                    'パラメータ名は@を除いた名前を指定します。
                    prmtr1.ParameterName = "name"
                    'パラメータの値を設定します。
                    prmtr1.Value = name
                    'パラメータをコマンドに追加します。
                    cmd.Parameters.Add(prmtr1)

                    'SQLiteへの橋渡しのアダプターを設定します。
                    Dim sda As SQLiteDataAdapter = New SQLiteDataAdapter()

                    'SELECTコマンドを設定します。
                    sda.SelectCommand = cmd
                    'SELECTの実行及びフェッチ
                    sda.Fill(dt)

                    deletePath = dt.Rows(0)(0).ToString()

                    sda.Dispose()
                End Using

                'SQL文とコネクションを設定します。
                Using cmd As New SQLiteCommand("delete from exrecipe where name = @name", conn)
                    'パラメータの作成
                    Dim prmtr1 As SQLiteParameter = New SQLiteParameter()
                    'パラメータ名は@を除いた名前を指定します。
                    prmtr1.ParameterName = "name"
                    'パラメータの値を設定します。
                    prmtr1.Value = name
                    'パラメータをコマンドに追加します。
                    cmd.Parameters.Add(prmtr1)

                    'データ更新
                    cmd.ExecuteNonQuery()
                End Using

                'DataGridView1で選択されているすべての行を削除する
                Dim r As DataGridViewRow
                For Each r In DataGridView1.SelectedRows
                    If Not r.IsNewRow Then
                        DataGridView1.Rows.Remove(r)
                    End If
                Next r

                'SQL文とコネクションを設定します。
                Using cmd As New SQLiteCommand("SELECT name,genre,DateTime FROM exrecipe WHERE @DateTime", conn)
                    Dim prmtr As New SQLiteParameter("@DateTime", GetDate.ToString("yyyy年MM月dd日"))
                    'パラメータをコマンドに追加します。
                    cmd.Parameters.Add(prmtr)

                    'SQLiteへの橋渡しのアダプターを設定します。
                    Dim sda As SQLiteDataAdapter = New SQLiteDataAdapter()

                    'SELECTコマンドを設定します。
                    sda.SelectCommand = cmd
                    'SELECTの実行及びフェッチ
                    sda.Fill(dt)
                    'グリッドに表示します。
                    DataGridView1.DataSource = dt

                    sda.Dispose()
                End Using
            End Using

            ' ------------------------------------------------------
            ' ファイルの 削除処理
            ' ------------------------------------------------------
            Try
                System.IO.File.Delete(deletePath)
            Catch ex As Exception
                MsgBox(ex.Message, MsgBoxStyle.OkOnly + MsgBoxStyle.Critical, "エラー")
            End Try

    一番目の空白をなくす方法が分からない状態です。

    ソースはSQLiteのexRecipeというテーブルから
    1番目:選択した項目のDIRを取得するSQL文を実行
    2番目:選択したSQL文の削除
    DataGridViewの中身をクリアして
    最後に今日の日付のSQL文を表示するプログラムです。
    そして、DIRのPDFを削除しています

    なぜか、空白が出来てしまうので、良く分からない状態でいます。




    • 編集済み RappyKakuwane 2022年12月9日 5:06 プログラムの説明をいれました
    2022年12月9日 4:48

すべての返信

  • 何をしたいのか、何が質問なのか質問文から分かっていませんが・・・

    DataGridView のある行を選択してから[レシピの削除]ボタンをクリックしたとき、その行を消したい(中身を空白にするだけでなく行ごと表示されないようにしたい)のだが、現状は質問の 2 つ目の画像にあるように中身が空白の行が残ってしまうということですか?

    であれば、アプリの構造を以下のようにして、

    SQLite ⇔ DataTable ⇔ BindingSource ⇔ DataGridView

    [レシピの削除]ボタンクリックのイベントハンドラで BindingSource.RemoveCurrent() を実行すれば良いです。

    以下の記事は、CSV ファイル ⇔ DataTable ⇔ BindingSource ⇔ DataGridView という構造で、button2_Click でそれを行っています。

    CSV ファイルを DataGridView に表示
    http://surferonwww.info/BlogEngine/post/2020/09/11/show-date-in-csv-file-on-datagridview.aspx




    • 編集済み SurferOnWww 2022年12月9日 6:27 訂正
    2022年12月9日 5:29
  • 質問者さん、無言ですが、回答したのでそれに対するフィードバックを返してください。役に立った/立たなかったぐらいはすぐに返せるのでは? 役に立たなかったならどこがダメかを書くとより期待に近い回答が出てくるかも。
    2022年12月10日 0:44
  • すみません、BindingSourceの使い方を調べていて、参考書になくてC#のサイトを見ていたのですが、使い方をまだ理解できないでいます。ごめんなさい。
    2022年12月10日 7:14
  • デザイン画面でツールボックスから Form にドラッグ&ドロップすれば使えるようになります。あとでサンプルを書いておきます。
    2022年12月10日 8:01
  • 上のレスで「あとでサンプルを書いておきます。」と書いた件です。

    以下の SQLite のテーブル Movie を使います。Id 列は主キーで AUTOINCREMENT です。



    デザイン画面でツールボックスから DataGridView, BindingSource と TextBox を 2 つドラッグ&ドロップします。



    コードは以下の通りです。C# が読めなければ変換サービスがありますので使ってみてください。

    Telerik Code Converter
    https://converter.telerik.com/

    using System;
    using System.Data;
    using System.Data.SQLite;
    using System.Windows.Forms;
    
    namespace WindowsFormsSQLite
    {
        public partial class Form1 : Form
        {
            private SQLiteDataAdapter adapter;
            private DataTable table;
    
            public Form1()
            {
                InitializeComponent();
    
                this.dataGridView1.DataSource = this.bindingSource1;
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                var connString = @"Data Source=C:\Users...\Movie.db";
                var selectQuery = "SELECT Id, Title, ReleaseDate, Genre, Price FROM Movie";
    
                var connection = new SQLiteConnection(connString);
                var command = new SQLiteCommand(selectQuery, connection);
                this.adapter = new SQLiteDataAdapter();
                this.adapter.SelectCommand = command;
                new SQLiteCommandBuilder(this.adapter);
    
                this.table = new DataTable();
                this.adapter.Fill(table);
                this.bindingSource1.DataSource = this.table;
            }
                   
            private void Update_Click(object sender, EventArgs e)
            {            
                this.adapter.Update(this.table);
            }
    
            private void Remove_Click(object sender, EventArgs e)
            {
                this.bindingSource1.RemoveCurrent();
            }
        }
    }

    実行すると以下のようになり、行を選択を選択(▶ 印の行がそれ)して[RemoveItem]ボタンをクリックすれば上のコードの Remove_Click メソッドが動いて行が削除されます。



    さらに[UpdateAll]ボタンをクリックすればその結果が SQLite に反映されます。コードの SQLiteCommandBuilder がそのあたりのキモです。是非それも勉強することをお勧めします。



    • 編集済み SurferOnWww 2022年12月10日 8:30 訂正
    2022年12月10日 8:26
  • new SQLiteCommandBuilder(this.adapter);

    このあたりで構文えらーとなったので、試行錯誤して自分なりにソースを変えて動かしてみました。

    動く段階まで出来たのですが、、、、

    [UpdateAll]でエラーになって、いる状態です。

    すみません。コードのどこが不味いのか分からない状態です。

    Imports System
    Imports System.Data
    Imports System.Data.SQLite
    Imports System.Windows.Forms

    Public Class Form1

        Dim sda As SQLiteDataAdapter = New SQLiteDataAdapter()
        Dim table As DataTable = New DataTable()

        Public Sub New()
            InitializeComponent()
            Me.DataGridView1.DataSource = Me.BindingSource1
        End Sub

        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim builder As SQLiteConnectionStringBuilder = New SQLiteConnectionStringBuilder()
            'SQLiteのファイルへのパスを設定します。
            builder.DataSource = ".\test.db"
            '接続情報を使ってコネクションを生成します。
            Using conn As New SQLiteConnection(builder.ConnectionString)
                'SQL文とコネクションを設定します。
                Using cmd As New SQLiteCommand("SELECT * FROM Movie", conn)
                    sda = New SQLiteDataAdapter()
                    sda.SelectCommand = cmd
                    Me.table = New DataTable()
                    sda.Fill(table)
                    Me.BindingSource1.DataSource = Me.table

                End Using
            End Using
        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            sda.Update(Me.table)
        End Sub

        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Me.BindingSource1.RemoveCurrent()
        End Sub

    End Class

    2022年12月10日 10:43
  • 質問する際の基本のキですが、エラーメッセージをコピペしてください。エラーメッセージには非常に重要な情報が含まれていて、それだけ見れば原因と解決策が分かることも多いのですよ。

    > new SQLiteCommandBuilder(this.adapter);
    > このあたりで構文えらーとなったので、試行錯誤して自分なりにソースを変えて動かしてみました。

    new SQLiteCommandBuilder(this.adapter); を削除した結果、

    >[UpdateAll]でエラーになって、いる状態です。

    になったのだと思いますが、それは当たり前です。

    先のレスで「コードの SQLiteCommandBuilder がそのあたりのキモです」と書いたのですから、Microsoft のドキュメントを読むなどしてそこを勉強しましょう。

    なぜダメなのかを説明しておきます。以下の記事の図1と図2を見てください。

    DB 設計者のための明解 ADO.NET 第 1 回
    https://learn.microsoft.com/ja-jp/previous-versions/cc482903(v=msdn.10)?redirectedfrom=MSDN

    図2の DataSet / DataTable の左に BindingSource 経由で DataGridView があるというのが紹介したアプリの構造です。

    ユーザーが DataGridView を編集すると、その結果は図1にあるように DataSet の中の TataTable に反映されます。

    Update で編集された DataTable の内容を Update, Delete, Insert コマンドで一気に DB に書き戻すようになっています。

    new SQLiteCommandBuilder(this.adapter); がないと Update, Delete, Insert を動かすコードが生成されないのです。

    2022年12月10日 12:37
  • もう一つ。SQLiteConnection と SQLiteCommand を using 句を使って破棄してますが、それもダメです。
    2022年12月10日 14:54
  • RappyKakuwaneさん、こんにちは。フォーラムオペレーターのKumoです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ご質問いただいた件ですが、その後いかがでしょうか。

    より詳しい情報を追加いただければ、回答が付きやすくなります。

    よろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2022年12月12日 1:50
    モデレータ
  • 変換すると

    ここで構文エラーとなっていて、直し方がどうしてもわからないです。


    • 編集済み RappyKakuwane 2022年12月12日 3:53 間違えました
    2022年12月12日 3:53
  • VB.NET の場合は以下のようにしないとダメです。

    Dim builder = New SQLiteCommandBuilder(Me.adapter)

    2022年12月12日 5:33
  • 回答をもらっているのにいつまでも放置しておかないでください。失礼ですよ。
    2022年12月14日 3:34