ゲームエフェクトデザイナーのブログ | A Real-Time VFX Artist's Blog

About Making Materials on UE, Making Tools with C#, etc

C# DataGridViewの列の値に0から始まる番号を入力する

DataGridViewに「No」という列があったとして、

 

// 行数をカウント
int count = RowsCount();

// Noを振り直す
for (int i = 0; i < count; i++)
{
    dgv[0, i].Value = i;
}


とか、もしくは‥

// Noを振り直す
int i = 0;
foreach (ar item in dgv.Rows)
{
    dgv[0, i].Value = i;
    i++
}


とかで可能な訳ですが、これはあくまでDataGridVIew上の並び順で値を0から入力していきます。

例えば列ヘッダーをクリックして昇順ソートした状態で実行すると、ソートされた並び順で番号が入力されていってしまいます。

つまり、内部データである DataTable での並び順と一致しなくなってしまいます。

なので DataTableの行情報にアクセスして値を書き替えてあげる必要があります。

このような感じ。

// Noを振り直す
int i = 0;

foreach (DataRow r in taskDataSet.taskDataTable.Rows)
{
    r["No"] = i;
    i++;
}


といった感じで実行することで、うまくいきました。

C# DataGridViewにDataTableをデザイナでバインドしている際のフィルタのサンプル

Visual Studioデザイナはコントロールの作成やプロパティの設定などをGUIを通して直感的に作業でき、ほとんどコーディングせずに制作できてしまうのでプログラム初心者には大変ありがたい機能です。

しかしその反面、何か困った時にデザイナを使った場合の解説がなかなか見つかりません。

例えば DataGridView に DataTable をバインドした場合のケースです。

こちら詰まったのでメモっておきたいと思います。

続きを読む

C# DataGridViewの表示がおかしくなった時の対処法

Visual StudioDesigner(デザイナ)を使用して DataGridView を作成&編集していると、DataTableの列ヘッダー情報を更新しても表示に反映されなかったり、突然 DataGridView そのものが表示されなくなったり、列ヘッダーをクリックして昇順・降順ソートをした際の▼マーク(グリフ)が表示されなくなったりと、表示の不具合が色々と起こります。

DataGridViewコントロールやプロパティを全てコードで記述している場合には起こらない、Designer使用時ならではの不具合のような気がします。

そんな時の対処方法についてメモっておきたいと思います。

続きを読む

C# DataGridViewのソートとフィルタのサンプル

WindowsFormでのDataGridViewのソートとフィルタのサンプルです。

こちらの2つの記事を参考にさせていただきました。

【C#入門】DataTableの使い方(Select、Sort、Compute、LINQも解説) | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト

DataGridコントロールで並び替え順やフィルタを指定するには?:.NET TIPS - @IT


外観はこんな感じ。

f:id:moko_03_25:20181004002856j:plain

コードはこんな感じ。

Formpublic partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    // データセットを作成
    DataSet dataSet = new DataSet("タスク管理");

    // データテーブルを作成
    DataTable table = new DataTable("Table");

    private void Form1_Load(object sender, EventArgs e)
    {
        // データテーブルに列を追加 table.Columns.Add("カテゴリ");
        table.Columns.Add("内容");
        table.Columns.Add("優先度");
        table.Columns.Add("進捗");

        // データセットにデータテーブルを追加
        dataSet.Tables.Add(table);

        // テーブルにデータを追加
        table.Rows.Add("要望", "レベル", "低", "進行中");
        table.Rows.Add("バグ", "固まる", "高", "進行中");
        table.Rows.Add("追加", "ボタン", "中", "未着手");
        table.Rows.Add("要望", "入力欄", "高", "完了");
        table.Rows.Add("バグ", "止まる", "中", "進行中");
        table.Rows.Add("バグ", "落ちる", "低", "未着手");
        table.Rows.Add("追加", "設定済", "高", "完了");
        table.Rows.Add("要望", "最前面", "中", "完了");

        // データグリッドにテーブルを表示する
        this.dgv.DataSource = table;
    }

    // ボタン「Sort」を押す
    private void button1_Click(object sender, EventArgs e)
    {
        // ソートの指定
        table.DefaultView.Sort = "カテゴリ ASC";
    }

    // ボタン「Filter」を押す
    private void button2_Click(object sender, EventArgs e)
    {
        // フィルタの指定
        table.DefaultView.RowFilter = "進捗 <> '完了'";
    }
}

 

「Sotr」ボタンを押した場合。カテゴリ欄が昇順でソートされました。

f:id:moko_03_25:20181004002900j:plain

「Filter」ボタンを押した場合。進捗が完了のもの以外を表示しました。

f:id:moko_03_25:20181004002905j:plain

ひとまずメモでした!

C# カラー管理クラスを考える

Formのコントロールの各色をRGB値でカラー指定したいという場合に「カラー管理クラスを作った方が良さそうだな」と思い、色の値を扱うプロパティを試してみました。

テストで作成したのはこちら。

f:id:moko_03_25:20180927012732g:plain

コードはこちらのような感じ。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    // ボタン1クリック
    private void button1_Click(object sender, EventArgs e)
    {
        MyColor mc = new MyColor();

        // 配列の場合
        this.panel1.BackColor = Color.FromArgb(mc.c[0], mc.c[1], mc.c[2]);
    }

    // ボタン2クリック
    private void button2_Click(object sender, EventArgs e)
    {
        MyColor mc = new MyColor();

        // カラーインスタンスの場合
        this.panel1.BackColor = mc.col;
    }
}

// カラー管理クラス
public class MyColor
{
    // 配列を扱ったプロパティ
    public int c { get; set; } = { 200, 120, 70 };

    // カラークラスを使ったプロパティ
    public Color col { get; set; } = Color.FromArgb(70, 150, 200);
}


配列のプロパティとColorクラス型のプロパティのどちらも大丈夫そうですね。

カラー値を取り出す際にはColorクラス型の方が楽ですが、値を設定ファイルに保存して次回起動時に反映させるのは配列型の方が楽ですかね。。

ということは、配列のプロパティとそのプロパティを利用してColorオブジェクトを生成するメソッドを用意するのが良いのかな?

という訳で下記のような感じで試してみたところ、こちらも問題ないようでした。
これなら呼び出すのは楽。。

▼呼び出し側 ボタンクリックイベント
this.panel1.BackColor = mc.MakeRGB();

▼クラス側
// 配列を扱ったプロパティ
public int color { get; set; } = { 200, 120, 70 };

// Colorオブジェクト生成メソッド
public Color MakeRGB(int i)
{
    Color c = Color.FromArgb(i[0], i[1], i[2]);
    return (c);
}

 
また、こんな風に set は配列だけど get は Color型‥みたいな書き方はできないのかな?
まだ知らないだけでできそう。

// set は配列だけど get はColor型‥はダメでした
public int c
{
    get { return (Color.FromArgb(this.c[0], this.c[1], this.c[2])); }
    set { this.c = value; }
}


何か分かったら追記予定。

C# RPG風にテキストメッセージを1文字ずつ表示させる

案外ググっても出てこないのでメモ。

テストで作ったものはこちら。
Button1 を押すと Label1 に文字列を一文字ずつ表示します。

f:id:moko_03_25:20180924201537g:plain

やっていることは以下のような感じ。

・各行ごとに string型の変数を用意

・foreach で string型の引数から1文字ずつ取り出して文字列に「追加」する
 そして少し待機させる
 空白文字だった場合は待機させない

・行間も待機させる


空白文字の場合は待機させると不自然になり、スルーすると自然になりました。

コードはこんな感じ。
非同期処理について全くと言って良いほど理解していない状態なので、その点ご了承ください。

private async void button1_ClickAsync(object sender, EventArgs e)
{
    string s1 = "ほにゃらら は レベルアップしました!" + "\r\n";
    string s2 = "\r\n" + "ちから が 2 あがった!";
    string s3 = "\r\n" + "すばやさ が 1 あがった!";
    string s4 = "\r\n" + "かしこさ が 2 あがった!";

    string output = "";

    int waitTimeChar = 50; // 一文字の待機時間
    int waitTimeLine = 300; // 行間の待機時間

    await OutputMessage(s1);
    await Task.Delay(waitTimeLine);

    await OutputMessage(s2);
    await Task.Delay(waitTimeLine);

    await OutputMessage(s4);
    await Task.Delay(waitTimeLine);

    await OutputMessage(s3);


    // 関数:1文字ずつ表示する
    async Task OutputMessage(string s)
    {
        // foreachで1文字ずつ処理(後半)
        foreach (char c in s)
        {
            // 1文字追加
            output += c.ToString();

            // ラベルに表示
            this.label1.Text = output;

            // 空白文字以外にディレイさせる
            if ("" != c.ToString())
            {
                // ディレイ
                await Task.Delay(waitTimeChar);
            }
        }
    }
}


以上、参考になれば幸いです。

※自分用のメモ

文字列から1文字取得する、文字列内の文字を列挙する - .NET Tips (VB.NET,C#...)

C# で Thread.Sleep はあきまへん

async、awaitそしてTaskについて(非同期とは何なのか) - SE(たぶん)の雑感記

C# Taskの待ちかた集

非同期メソッド - C# によるプログラミング入門 | ++C++; // 未確認飛行 C

C# Labelの主なプロパティ

良く忘れるのでメモ。

デフォルトから変えることが多いものを中心にメモっています。

◆動作

 

◆配置

AutoSize ‥ Textの長さに合わせて自動的にサイズが決まる
       右寄せしたい場合などは False にしておく

◆表示

TextAlign ‥ Text を右寄せにしたりできるが AutoSize を False にしないと効かない