プロジェクト構成
適切な粒度でライブラリ化して開発資産にする(2/2) - @IT
エクセル
表を選択後、コンテキストメニューから並べ替え、ユーザー設定の並べ替えにてタスク一覧を管理。
excel-microsoft.info www.becoolusers.com
クリックワンス
Insider.NET > ClickOnceの真実 - @IT
タイマー処理
テーブルレイアウト
手順 4: TableLayoutPanel コントロールを使用したフォームのレイアウトの設定
SQL Server 2008 ページング
itmemo.net-luck.com kosukety.org
table - pubs / sample
select * from ( select *, ROW_NUMBER() over(order by phone) rownum from authors ) t where rownum between 10 and 20
データグリッドビュー
参照用共通カスタムデータグリッドビュー
// ReadonlyDataGridView.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WinFormUc { public partial class ReadonlyDataGridView : DataGridView { public ReadonlyDataGridView() { InitializeComponent(); // 初期設定 this.SelectionMode = DataGridViewSelectionMode.FullRowSelect; this.MultiSelect = false; this.AllowUserToAddRows = false; this.AllowUserToResizeRows = false; this.RowHeadersVisible = false; this.ReadOnly = true; } protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); } } }
// DataGridViewHelper.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WinFormUc { /// <summary> /// DataGridViewHelperクラス /// </summary> public static class DataGridViewHelper { #region カラム追加 /// <summary> /// カラム追加 /// </summary> /// <param name="dgv">対象グリッドビュー</param> /// <param name="propertyName">プロパティ名</param> /// <param name="headerText">ヘッダーテキスト</param> /// <param name="visible">列の表示/非表示</param> /// <param name="witdh">列幅</param> public static void AddColumn(DataGridView dgv, string propertyName, string headerText, bool visible, int witdh) { // DataGridViewColumnオブジェクトを生成 DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn(); // セルに表示するデータソースの指定(DataRowの列名や、独自クラスのプロパティ名を指定) column.DataPropertyName = propertyName; // ヘッダーのテキスト column.HeaderText = headerText; // 列の表示/非表示 column.Visible = visible; // 列幅 column.Width = witdh; // ユーザーによる列幅の変更可否 column.Resizable = DataGridViewTriState.True; // 追加 dgv.Columns.Add(column); } #endregion } }
// SampleForm.cs private void btnSetGrid_Click(object sender, EventArgs e) { DataGridViewHelper.AddColumn(this.commonDataGridView1, "col_0", "データ0", true, 100); DataGridViewHelper.AddColumn(this.commonDataGridView1, "col_1", "データ1", true, 100); DataGridViewHelper.AddColumn(this.commonDataGridView1, "col_2", "データ2", true, 100); // データグリッドビューの設定 this.commonDataGridView1.AutoGenerateColumns = false; this.commonDataGridView1.DataSource = this.MakeDataTable(); // ソート設定 foreach (DataGridViewColumn c in this.commonDataGridView1.Columns) { c.SortMode = DataGridViewColumnSortMode.Programmatic; } this.commonDataGridView1.ColumnHeaderMouseClick += CommonDataGridView1_ColumnHeaderMouseClick; } private void CommonDataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { // ヘッダのDataPropertyNameによりsortするsqlを実行 DataGridView dgv = sender as DataGridView; MessageBox.Show("header click:" + this.commonDataGridView1.Columns[e.ColumnIndex].DataPropertyName); } private DataTable MakeDataTable() { string[] id = { "S0001", "S0002", "S0003", "S0004", "S0005", "S0006" }; string[] name = { "あんぱん", "メロンパン", "カレーパン", "いちごじゃむパン", "チョココロネ", "クロワッサン" }; string[] value = { "100", "105", "110", "115", "120", "125" }; DataTable dt = new DataTable(); dt.Columns.Add("col_0"); dt.Columns.Add("col_1"); dt.Columns.Add("col_2"); // DataTableにデータを格納します。 for (int i = 0; i < 5; i++) { dt.Rows.Add(dt.NewRow()); dt.Rows[i]["col_0"] = id[i]; dt.Rows[i]["col_1"] = name[i]; dt.Rows[i]["col_2"] = value[i]; } return dt; }
ユーザーコントロールを作成する
http://blog.hiros-dot.net/?cat=153
TextBoxに数字しか入力できないようにする: .NET Tips: C#, VB.NET
数値入力テキストボックス
using System; using System.ComponentModel; using System.Windows.Forms; using System.Security.Permissions; namespace WinFormUc { /// <summary> /// 数値入力テキストボックス /// </summary> public partial class TextBoxNumeric : TextBox { #region 変数・プロパティ /// <summary> /// メッセージ:WM_PASTE /// </summary> private const int WM_PASTE = 0x302; /// <summary> /// 数字以外で入力が可能な文字 /// </summary> private char[] allowKeyChars; /// <summary> /// IMEモード /// </summary> [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new ImeMode ImeMode { get { return base.ImeMode; } set { } } /// <summary> /// MaxLength /// </summary> [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public new int MaxLength { get { return base.MaxLength; } set { base.MaxLength = value; } } #endregion #region コンストラクタ /// <summary> /// コンストラクタ /// </summary> public TextBoxNumeric() : base() { //IMEを無効にする base.ImeMode = ImeMode.Disable; //数字以外で入力が可能な文字 this.SetAllowKeyChars(new char[] { '\b' }); } #endregion #region WndProc /// <summary> /// WndProc /// </summary> [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { if (m.Msg == WM_PASTE) { IDataObject iData = Clipboard.GetDataObject(); //文字列がクリップボードにあるか if (iData != null && iData.GetDataPresent(DataFormats.Text)) { string clipStr = (string)iData.GetData(DataFormats.Text); //クリップボードの文字列が数字のみか調べる if (!System.Text.RegularExpressions.Regex.IsMatch( clipStr, @"^[0-9]+$")) { return; } } } base.WndProc(ref m); } #endregion #region 数字以外で入力が可能な文字を設定する /// <summary> /// 数字以外で入力が可能な文字を設定する /// </summary> public void SetAllowKeyChars(char[] keyChars) { this.allowKeyChars = keyChars; } #endregion #region 数字以外で入力が可能な文字を取得する /// <summary> /// 数字以外で入力が可能な文字を取得する /// </summary> public char[] GetAllowKeyChars() { return this.allowKeyChars; } #endregion #region OnKeyPress /// <summary> /// OnKeyPress /// </summary> protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); if (((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) && e.KeyChar == (char)22) { // ctrl + v } else if (((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) && e.KeyChar == (char)3) { // ctrl + c } else //数字以外が入力された時はキャンセルする if ((e.KeyChar < '0' || '9' < e.KeyChar) && Array.IndexOf(this.allowKeyChars, e.KeyChar) < 0) { e.Handled = true; } } #endregion } }
日付用テキストボックス
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Security.Permissions; namespace WinFormUc { /// <summary> /// 日付用テキストボックス /// </summary> public partial class TextBoxDate : TextBox { #region 変数・プロパティ /// <summary> /// メッセージ:WM_PASTE /// </summary> protected const int WM_PASTE = 0x302; /// <summary> /// 数字以外で入力が可能な文字 /// </summary> private char[] allowKeyChars; /// <summary> /// IMEモード /// </summary> [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new ImeMode ImeMode { get { return base.ImeMode; } set { } } /// <summary> /// MaxLength /// </summary> [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public new int MaxLength { get { return base.MaxLength; } set { base.MaxLength = value; } } #endregion #region コンストラクタ /// <summary> /// コンストラクタ /// </summary> public TextBoxDate() : base() { //数字以外で入力が可能な文字 this.SetAllowKeyChars(new char[] { '\b', '/' }); } #endregion #region WndProc /// <summary> /// WndProc /// </summary> [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { if (m.Msg == WM_PASTE) { IDataObject iData = Clipboard.GetDataObject(); //文字列がクリップボードにあるか if (iData != null && iData.GetDataPresent(DataFormats.Text)) { string clipStr = (string)iData.GetData(DataFormats.Text); //クリップボードの文字列が数字 or '/'か調べる if (!System.Text.RegularExpressions.Regex.IsMatch( clipStr, @"^([0-9]|/)+$")) { return; } } } base.WndProc(ref m); } #endregion #region OnLeave /// <summary> /// OnLeave /// </summary> protected override void OnLeave(EventArgs e) { base.OnLeave(e); this.Text = this.ConvertDateFormat(this.Text); } #endregion #region OnKeyPress /// <summary> /// OnKeyPress /// </summary> protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); if (((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) && e.KeyChar == (char)22) { // ctrl + v } else if (((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) && e.KeyChar == (char)3) { // ctrl + c } else //数字以外が入力された時はキャンセルする if ((e.KeyChar < '0' || '9' < e.KeyChar) && Array.IndexOf(this.allowKeyChars, e.KeyChar) < 0) { e.Handled = true; } } #endregion #region 数字以外で入力が可能な文字を設定する /// <summary> /// 数字以外で入力が可能な文字を設定する /// </summary> public void SetAllowKeyChars(char[] keyChars) { this.allowKeyChars = keyChars; } #endregion #region 数字以外で入力が可能な文字を取得する /// <summary> /// 数字以外で入力が可能な文字を取得する /// </summary> public char[] GetAllowKeyChars() { return this.allowKeyChars; } #endregion #region 入力された日付文字列を変換 /// <summary> /// 入力された日付文字列を変換 /// </summary> /// <param name="inDate">入力日付文字列</param> /// <returns>変換した日付文字列</returns> private string ConvertDateFormat(string inDate) { string resultStr = inDate; this.BackColor = Color.White; if (Regex.IsMatch(inDate, @"^[0-9]{6}99$")) { // yyyyMMdd:format:で末尾2桁が99の場合 string year = inDate.Substring(0, 4); string month = inDate.Substring(4, 2); string dateStr = string.Format("{0}/{1}/{2}", year, month, 1); DateTime checktDate; if (DateTime.TryParse(dateStr, out checktDate)) { DateTime d = checktDate.AddMonths(1).AddDays(-1); resultStr = d.ToString("yyyy/MM/dd"); } else { this.BackColor = Color.Pink; } } else if (Regex.IsMatch(inDate, @"^[0-9]{8}$")) { // yyyyMMdd:format:で末尾2桁が99以外の場合 string year = inDate.Substring(0, 4); string month = inDate.Substring(4, 2); string day = inDate.Substring(6, 2); string dateStr = string.Format("{0}/{1}/{2}", year, month, day); DateTime checkDate; if (DateTime.TryParse(dateStr, out checkDate)) { resultStr = dateStr; } else { this.BackColor = Color.Pink; } } else if (Regex.IsMatch(inDate, @"^[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}$")) { // yyyy/MM/dd:formatの場合 if (Regex.IsMatch(inDate, @"^[0-9]{4}/[0-9]{1,2}/99$")) { // yyyy/MM/dd:format:で末尾2桁が99の場合 string[] dateDatas = inDate.Split('/'); string year = dateDatas[0]; string month = dateDatas[1]; string dateStr = string.Format("{0}/{1}/{2}", year, month, 1); DateTime checkDate; if (DateTime.TryParse(dateStr, out checkDate)) { resultStr = checkDate.AddMonths(1).AddDays(-1).ToString("yyyy/MM/dd"); } else { this.BackColor = Color.Pink; } } else { // yyyy/MM/dd:format:で末尾2桁が99以外の場合 DateTime result; if (DateTime.TryParse(inDate, out result)) { resultStr = inDate; } else { this.BackColor = Color.Pink; } } } else { this.BackColor = Color.Pink; } return resultStr; } #endregion } }
コンボボックスの注意点
[Winforms] ComboBoxでDataSource=nullをすると、ドロップダウンに空行が残ってしまう
ComboBox(Forms) の DataSource を使用するときの注意点netplanetes.wordpress.com
グローバル変数
フォームをTOPへ表示
log4net
Apache log4net – Download Apache log4net - Apache log4net
// sample.cs - Logger Logger.Info("test");
// Assemblyinfo.cs - log4net設定 [assembly: log4net.Config.XmlConfigurator(Watch = true)]
// Logger.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net; namespace xxxx.Utility.Log { /// <summary> /// Logヘルパークラス /// </summary> public static class Logger { #region 変数・プロパティ /// <summary> /// Logger /// </summary> public static ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion #region /// <summary> /// Fatal:システム停止するような致命的な障害 /// </summary> /// <param name="msg"></param> public static void Fatal(string msg) { logger.Fatal(msg); } #endregion #region /// <summary> /// Error:システム停止はしないが、問題となる障害 /// </summary> /// <param name="msg"></param> public static void Error(string msg) { logger.Error(msg); } #endregion #region /// <summary> /// Warn:障害ではない注意警告 /// </summary> /// <param name="msg"></param> public static void Warn(string msg) { logger.Warn(msg); } #endregion #region /// <summary> /// Info:操作ログなどの情報 /// </summary> /// <param name="msg"></param> public static void Info(string msg) { logger.Info(msg); } #endregion #region /// <summary> /// Debug:開発用のデバッグメッセージ /// </summary> /// <param name="msg"></param> public static void Debug(string msg) { logger.Debug(msg); } #endregion } }
<!-- app.config --> <?xml version="1.0" encoding="utf-8" ?> <configuration> <!--これを最初に持ってくること--> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <!-- log4net --> <log4net> <!-- file --> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <!-- ログ・ファイル名の先頭部分 --> <param name="File" value=".\log\Trace_" /> <!-- ファイル名の日付部分 --> <param name="DatePattern" value='yyyyMMdd".log"' /> <!-- 日付ごとにファイルを作成することを指定 --> <param name="RollingStyle" value="date" /> <!-- ログ・ファイル名が固定ではないので“false”を指定 --> <param name="StaticLogFileName" value="false" /> <!-- 追加書き込み --> <param name="AppendToFile" value="true" /> <!-- 全てのログ・レベルとする --> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMax" value="FATAL" /> <param name="LevelMin" value="DEBUG" /> </filter> <!-- rollingStyle がSizeまたはCompositeの時の最大ファイルサイズ --> <param name="MaximumFileSize" value="10MB" /> <!-- ファイルを切替えるマックス数。ここでは3世代まで管理する --> <param name="MaxSizeRollBackups" value="3" /> <!-- ログの出力書式(%C、%F、%l、%L、%Mの場合は処理負荷が高く)--> <layout type="log4net.Layout.PatternLayout"> <!--<ConversionPattern value="%d,[%-5p],%F(%L),%C,%M,%m%n" />--> <!--<ConversionPattern value="%d,[%-5p],%C,%M,%m%n" />--> <ConversionPattern value="%d,[%-5p],%m%n" /> </layout> </appender> <!-- console --> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> <layout type="log4net.Layout.PatternLayout"> <!--<ConversionPattern value="%d,[%-5p],%F(%L),%C,%M,%m%n" />--> <!--<ConversionPattern value="%d,[%-5p],%C,%M,%m%n" />--> <ConversionPattern value="%d,[%-5p],%m%n" /> </layout> </appender> <!-- trace --> <appender name="TraceAppender" type="log4net.Appender.TraceAppender"> <layout type="log4net.Layout.PatternLayout"> <!--<ConversionPattern value="%d,[%-5p],%F(%L),%C,%M,%m%n" />--> <!--<ConversionPattern value="%d,[%-5p],%C,%M,%m%n" />--> <ConversionPattern value="%d,[%-5p],%m%n" /> </layout> </appender> <root> <!-- 警告以上のログを出力したい場合 --> <level value="All" /> <!-- どのログ出力先を使用するか --> <appender-ref ref="RollingFileAppender" /> <appender-ref ref="ConsoleAppender" /> <appender-ref ref="TraceAppender" /> </root> </log4net> </configuration>