tag:crieit.net,2005:https://crieit.net/tags/WPF/feed
「WPF」の記事 - Crieit
Crieitでタグ「WPF」に投稿された最近の記事
2019-07-24T14:14:21+09:00
https://crieit.net/tags/WPF/feed
tag:crieit.net,2005:PublicArticle/15274
2019-07-24T14:14:21+09:00
2019-07-24T14:14:21+09:00
https://crieit.net/posts/WPF-5d37e92d057fb
【WPF】パソコンにインストールされてるソフトをチェックしてみる
<p>業務アプリなんかでは、<br />
データベースなど本体の他にアプリケーションの動作に必要なものがあったりします。</p>
<p>そういったものがインストールされているかどうか、プログラムでチェックする処理を書いてみました。</p>
<p>プログラムは一応前回のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/11/25/post-3218/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】chm ヘルプファイルを表示する</a></p>
<h2 id="クラスの追加"><a href="#%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E8%BF%BD%E5%8A%A0">クラスの追加</a></h2>
<h3 id="アプリケーション情報クラス"><a href="#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%83%85%E5%A0%B1%E3%82%AF%E3%83%A9%E3%82%B9">アプリケーション情報クラス</a></h3>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfAppCheck001.jpg" alt="クラスの追加" /></p>
<p>ソリューション・エクスプローラーからプロジェクトを右クリックし、「追加」>「クラス」を選択します。</p>
<p>名前を入力して「追加」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfAppCheck003.jpg" alt="名前を入力" /></p>
<p>プログラムは次のようにします。</p>
<p>UninstallApp.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp1
{
/// <summary>
/// アンインストールアプリケーション.
/// </summary>
public class UninstallApp
{
/// <summary>
/// 表示名
/// </summary>
public String DisplayName { set; get; }
/// <summary>
/// 表示バージョン
/// </summary>
public String DisplayVersion { set; get; }
/// <summary>
/// インストール日次
/// </summary>
public String InstallDate { set; get; }
/// <summary>
/// 発行元
/// </summary>
public String Publisher { set; get; }
}
}
</code></pre>
<p> </p>
<h3 id="レジストリチェッククラス"><a href="#%E3%83%AC%E3%82%B8%E3%82%B9%E3%83%88%E3%83%AA%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%82%AF%E3%83%A9%E3%82%B9">レジストリチェッククラス</a></h3>
<p>先程と同様、ソリューション・エクスプローラーからクラスを追加します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfAppCheck002.jpg" alt="名前の入力" /></p>
<p>RegistryUtil.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
namespace WpfApp1
{
public static class RegistryUtil
{
/// <summary>
/// 対象のアプリケーションがインストールされているかどうかを返します.
/// </summary>
/// <param name="appName"></param>
/// <returns></returns>
public static Boolean isInstalled(String appName)
{
List<UninstallApp> list = getUninstallAppList();
var result = list.Where(x => x.DisplayName.IndexOf(appName) > -1).ToList();
if (result.Count > 0)
{
return true;
}
return false;
}
/// <summary>
/// アンインストールアプリケーションの一覧を作成します.
/// </summary>
/// <returns></returns>
public static List<UninstallApp> getUninstallAppList()
{
String uninstallPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
RegistryKey regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(uninstallPath, false);
List<UninstallApp> list = new List<UninstallApp>();
if (regKey != null)
{
foreach (string subKey in regKey.GetSubKeyNames())
{
UninstallApp ap = new UninstallApp();
RegistryKey appkey = Registry.LocalMachine.OpenSubKey(uninstallPath + "\\" + subKey, false);
// 表示名
String displayName = GetValue(appkey, "DisplayName");
ap.DisplayName = displayName != "" ? displayName : subKey;
// バージョン
ap.DisplayVersion = GetValue(appkey, "DisplayVersion");
// インストール日時
ap.InstallDate = GetValue(appkey, "InstallDate");
// 発行元
ap.Publisher = GetValue(appkey, "Publisher");
list.Add(ap);
}
}
return list;
}
/// <summary>
/// レジストリキーから指定した名前のデータを取得します.
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <returns></returns>
private static String GetValue(RegistryKey key, String name)
{
var value = key.GetValue(name);
if (value != null)
{
return value.ToString();
}
return "";
}
}
}
</code></pre>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="起動時にチェックするように修正"><a href="#%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E4%BF%AE%E6%AD%A3">起動時にチェックするように修正</a></h3>
<pre><code> public MainWindow()
{
InitializeComponent();
if (!RegistryUtil.isInstalled("Oracle"))
{
MessageBox.Show("Oracleがインストールされていません。", "起動時チェック");
this.Close();
}
.
.
.
省略
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfAppCheck004.jpg" alt="アラートメッセージ" /></p>
<p>起動時にチェックが実施され、アラートメッセージが表示されました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>レジストリを参照するので、他にもいろいろと応用がききそうですね。</p>
<p>また、必要なアプリがインストールされていない場合に、<br />
インストーラーを起動するなんてこともできるかもしれませんね。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15252
2019-07-17T10:03:01+09:00
2019-07-17T10:03:01+09:00
https://crieit.net/posts/WPF-chm
【WPF】chm ヘルプファイルを表示する
<p>昨日に引き続きWPFのネタ。<br />
以前、Wordからchmファイルを作るソフトの紹介をしましたが、それで作成したファイルをWPFで表示する方法を調べてみました。</p>
<p>Windowsフォームであれば専用のクラスがあるのですが、WPF用のものは無いみたいなので、Windowsフォームのライブラリを利用して表示します。</p>
<p>プログラムは前回のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/11/24/post-3194/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】右クリックメニューでデータグリッドの内容をコピーする</a></p>
<p>chmを作成するソフトについては次の記事を参考にしてください。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/11/03/post-2997/" target="_blank" rel="noopener noreferrer" data-blogcard="1">Word から chm ファイルを生成する「doc2htmlhelp」</a></p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<h3 id="バインディングの追加"><a href="#%E3%83%90%E3%82%A4%E3%83%B3%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E8%BF%BD%E5%8A%A0">バインディングの追加</a></h3>
<p>F1キーでヘルプファイルを開けるように画面にバインディングの記述を追加します。</p>
<p>MainWindow.xaml</p>
<pre><code> <Window.InputBindings>
<KeyBinding Gesture="F1" Command="Help" />
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="Help" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
</code></pre>
<h3 id="メニューの追加"><a href="#%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC%E3%81%AE%E8%BF%BD%E5%8A%A0">メニューの追加</a></h3>
<p>PDF表示とは別に、ヘルプ表示用のメニューを追加します。</p>
<p>MainWindow.xaml</p>
<pre><code> <Menu Style="{StaticResource menu-normal}" Background="#e7efff" Height="auto" Width="auto" Margin="0,0,0,20">
<MenuItem Header="ファイル(_F)" >
<MenuItem x:Name="menu_exit" Header="終了(_X)" Click="menu_exit_Click"/>
</MenuItem>
<MenuItem Header="その他(_O)">
<MenuItem x:Name="menu_pdfview" Header="サンプルPDF表示(_P)" Click="menu_pdfview_Click"/>
<MenuItem x:Name="menu_chmview" Header="ヘルプ表示(_H)" Click="menu_chmview_Click"/>
</MenuItem>
</Menu>
</code></pre>
<p> </p>
<h2 id="ライブラリの追加"><a href="#%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E8%BF%BD%E5%8A%A0">ライブラリの追加</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfChm000.jpg" alt="参照の追加" /></p>
<p>ソリューション・エクスプローラーからプロジェクトの「参照」を右クリックし、「参照の追加」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfChm001.jpg" alt="ライブラリの選択" /></p>
<p>「System.Windows.Forms」を選択して、「OK」ボタンをクリックします。</p>
<h2 id="chmファイルの追加"><a href="#chm%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%BF%BD%E5%8A%A0">chmファイルの追加</a></h2>
<p>プロジェクト直下に作成した「chm」ファイルを追加します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfChm002.jpg" alt="chmファイルの追加" /></p>
<p>chmディレクトリに、作成したファイルをペーストします。</p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<p>アセンブリからアプリケーション実行ディレクトリを取得するためのライブラリをインポートします。</p>
<p>MainWindow.xaml.cs</p>
<pre><code>using System.Reflection;
</code></pre>
<h3 id="ヘルプ表示メソッドの追加"><a href="#%E3%83%98%E3%83%AB%E3%83%97%E8%A1%A8%E7%A4%BA%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0">ヘルプ表示メソッドの追加</a></h3>
<p>F1キー、メニューから呼び出すメソッドを追加します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// ヘルプファイルを表示します.
/// </summary>
private void ShowHelp()
{
Assembly mainAssembly = Assembly.GetExecutingAssembly();
String appDir = System.IO.Path.GetDirectoryName(mainAssembly.Location);
System.Windows.Forms.Help.ShowHelp(null, "file://" + appDir + "/chm/開発環境構築手順書.chm");
}
</code></pre>
<p> </p>
<h3 id="イベントメソッドの追加"><a href="#%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0">イベントメソッドの追加</a></h3>
<p>F1キー、ヘルプメニュークリック時のイベントメソッドを追加します。</p>
<pre><code> /// <summary>
/// F1キーでヘルプ表示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
logger.Info("F1押下");
ShowHelp();
}
/// <summary>
/// ヘルプ表示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menu_chmview_Click(object sender, RoutedEventArgs e)
{
logger.Info("ヘルプメニュークリック");
ShowHelp();
}
</code></pre>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfChm003.jpg" alt="ヘルプメニュー" /></p>
<p>ヘルプメニューに追加した「ヘルプ表示」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/11/WpfChm004.jpg" alt="chmファイルの表示" /></p>
<p>無事にヘルプファイルの表示ができました。</p>
<p>全然関係内容ですが。。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>アプリケーションのヘルプはPDFもいいですが、こういったヘルプファイルだとキーワード検索が簡単にできたり、<br />
目次から目的のヘルプを探しやすいのでユーザーフレンドリーかもしれませんね。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15248
2019-07-16T10:10:15+09:00
2019-07-16T10:10:15+09:00
https://crieit.net/posts/WPF-5d2d23f770ce9
【WPF】右クリックメニューでデータグリッドの内容をコピーする
<p>おはようございます。</p>
<p>データグリッドで、<br />
編集まではさせないけど内容のコピーが出来ると便利なシーンってありますよね。</p>
<p>そんな時は、右クリックでコンテキストメニューを表示して操作させるのがいいかもしれません。<br />
ということでやってみました。</p>
<p>ついでに、クリップボードの内容を貼り付ける操作と、行のコピーも実装してみます。</p>
<p>プログラムは下記の記事のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/11/02/post-2971/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】WebBrowser に PDFファイル を表示する</a></p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<p>まずは、データグリッドにコンテキストメニューを追加します。</p>
<p>MainWindow.xaml</p>
<pre><code> <DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,31,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem x:Name="ctm_namecopy" Header="名前をコピー(_C)" Click="ctm_namecopy_Click"/>
<MenuItem x:Name="ctm_namepaste" Header="名前を貼り付け(_V)" Click="ctm_namepaste_Click"/>
<MenuItem x:Name="ctm_rowcopy" Header="行をCSVとしてコピー(_R)" Click="ctm_rowcopy_Click"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="40" />
<DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="False" Width="80"/>
<DataGridTemplateColumn IsReadOnly="True" Header="性別" CellStyle="{StaticResource dgc-combo}" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbGender" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid<span>}</span><span>}</span>, Path=DataContext.GenderList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" SelectedValuePath="Cd" SelectedValue="{Binding Sex}" Width="50" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="False" Width="40"/>
<DataGridTemplateColumn IsReadOnly="True" Header="種別" CellStyle="{StaticResource dgc-combo}" Width="110">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbKind" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid<span>}</span><span>}</span>, Path=DataContext.KindList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="KindName" SelectedValuePath="KindCd" SelectedValue="{Binding Kind}" Width="110" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="False" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</code></pre>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="コピーメソッドの追加"><a href="#%E3%82%B3%E3%83%94%E3%83%BC%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0">コピーメソッドの追加</a></h3>
<p>次のようにメソッドを実装します。<br />
MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 名前をクリップボードにコピーします.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ctm_namecopy_Click(object sender, RoutedEventArgs e)
{
// 選択中のデータを取得
CatModel cat = this.dataGrid.SelectedItem as CatModel;
if (cat != null)
{
try
{
// クリップボードにコピー
Clipboard.SetText(cat.Name);
}
catch (Exception ex)
{
}
}
}
</code></pre>
<p> </p>
<p>データベース上で選択された行の、名前列をクリップボードにコピーします。<br />
簡単なものですね。</p>
<h3 id="貼り付けメソッドの追加"><a href="#%E8%B2%BC%E3%82%8A%E4%BB%98%E3%81%91%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0">貼り付けメソッドの追加</a></h3>
<p>次のようにメソッドを実装します。<br />
MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// クリップボードの名前を貼り付け
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ctm_namepaste_Click(object sender, RoutedEventArgs e)
{
// 選択中のデータを取得
CatModel cat = this.dataGrid.SelectedItem as CatModel;
if (cat != null)
{
String name = Clipboard.GetText();
cat.Name = name;
this.dataGrid.Items.Refresh();
}
}
</code></pre>
<p> </p>
<p>選択された行の名前列の内容をクリップボードの内容で上書きします。<br />
リフレッシュメソッドを呼び出すことで内容が即座に反映されます。</p>
<h3 id="行コピーメソッドの追加"><a href="#%E8%A1%8C%E3%82%B3%E3%83%94%E3%83%BC%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0">行コピーメソッドの追加</a></h3>
<p>次のようにメソッドを実装します。<br />
MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 行をカンマ区切り文字列にしてクリップボードにコピーします.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ctm_rowcopy_Click(object sender, RoutedEventArgs e)
{
// 選択中のデータを取得
CatModel cat = this.dataGrid.SelectedItem as CatModel;
if (cat != null)
{
// データをCSV形式に変換
String delmiter = ",";
StringBuilder sb = new StringBuilder();
sb.Append(cat.No).Append(delmiter);
sb.Append(cat.Name).Append(delmiter);
sb.Append(cat.Sex).Append(delmiter);
sb.Append(cat.Age).Append(delmiter);
KindConverter kindConverter = new KindConverter();
sb.Append(kindConverter.Convert(cat.Kind, null,null,null)).Append(delmiter);
sb.Append(cat.Favorite);
try
{
// クリップボードにコピー
Clipboard.SetText(sb.ToString());
}
catch (Exception ex)
{
}
}
}
</code></pre>
<p> </p>
<p>こちらはコピーの応用で、選択された行の内容をカンマ区切りに編集し<br />
クリップボードにコピーします。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>思っていたより簡単に実装できました。<br />
クライアントソフトならではの手軽さですかね。<br />
(WEBはセキュリティとかの問題でコピーとかが意外に面倒)</p>
<p>コンテキストメニュー自体は階層も持たすことができますし、<br />
色々なことに利用できそうですね。<br />
何か思いついたらやってみようと思います。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15237
2019-07-14T11:29:04+09:00
2019-07-14T11:29:04+09:00
https://crieit.net/posts/WPF-SQLite-5d2a9370e7173
【WPF】SQLiteのインサートが遅いので速度アップの方法を試してみる
<p>SQLiteって手軽で便利なんですが、<br />
大量のデータを扱うとなるとそれなりに速度が気になってきます。</p>
<p>試しに何万件のインサート処理をやってみたら案の定とても待ち切れる時間で処理が終わらなかったのでちょっと調べてみました。</p>
<p>プログラムは次の記事のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/06/29/post-1354/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】TextFieldParser で CSVファイルを読み込む</a></p>
<h2 id="元の処理"><a href="#%E5%85%83%E3%81%AE%E5%87%A6%E7%90%86">元の処理</a></h2>
<p>CSVを読み込んで一括登録する処理を変更してみます。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// CSV読込ボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void imp_button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = "";
ofd.DefaultExt = "*.csv";
if (ofd.ShowDialog() == false)
{
return;
}
List<Cat> list = readFile(ofd.FileName);
// 接続
int count = 0;
// データを追加する
using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
{
using (DataContext context = new DataContext(conn))
{
foreach (Cat cat in list)
{
// 対象のテーブルオブジェクトを取得
var table = context.GetTable<Cat>();
// データが存在するかどうか判定
if (table.SingleOrDefault(x => x.No == cat.No) == null)
{
// データ追加
table.InsertOnSubmit(cat);
// DBの変更を確定
context.SubmitChanges();
count++;
}
}
}
conn.Close();
}
MessageBox.Show(count + " / " + list.Count + " 件 のデータを取り込みました。");
// データ再検索
searchData();
}
</code></pre>
<h2 id="プラグマステートメントを設定"><a href="#%E3%83%97%E3%83%A9%E3%82%B0%E3%83%9E%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E8%A8%AD%E5%AE%9A">プラグマステートメントを設定</a></h2>
<p>まずはプラグマというステートメントを設定してみます。<br />
(プラグマステートメントとは、SQLite ライブラリの動作を変更するためのものです。)</p>
<p>次の記事に色々と詳しく書いてありますので参考にしてみてください。</p>
<blockquote>
<p>参考 : <a target="_blank" rel="nofollow noopener" href="http://devlights.hatenablog.com/entry/2014/02/01/151642">http://devlights.hatenablog.com/entry/2014/02/01/151642</a></p>
</blockquote>
<pre><code> using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite;version=3;synchronous=Normal;journal mode=Wal"))
{
using (DataContext context = new DataContext(conn))
{
foreach (Cat cat in list)
{
// 対象のテーブルオブジェクトを取得
var table = context.GetTable<Cat>();
// データが存在するかどうか判定
if (table.SingleOrDefault(x => x.No == cat.No) == null)
{
// データ追加
table.InsertOnSubmit(cat);
// DBの変更を確定
context.SubmitChanges();
count++;
}
}
}
conn.Close();
}
</code></pre>
<p>接続文字列にオプションを追加する方式でやってみました。</p>
<p>詳細に処理時間を載せませんが、処理速度の改善が見られました。</p>
<h2 id="明示的にトランザクションを開始する"><a href="#%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AB%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E9%96%8B%E5%A7%8B%E3%81%99%E3%82%8B">明示的にトランザクションを開始する</a></h2>
<p>これは結構有名な話しですが、<br />
一括処理する際にちゃんと明示的にトランザクションを制御しないと、<br />
1件毎にそれなりに時間のかかるトランザクション処理が実行されてしまうので、明示的にトランザクションを開始するように変更します。</p>
<pre><code> using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite;version=3;synchronous=Normal;journal mode=Wal"))
{
using (DataContext context = new DataContext(conn))
{
using (var ts = conn.BeginTransaction())
{
foreach (Cat cat in list)
{
// 対象のテーブルオブジェクトを取得
var table = context.GetTable<Cat>();
// データが存在するかどうか判定
if (table.SingleOrDefault(x => x.No == cat.No) == null)
{
// データ追加
table.InsertOnSubmit(cat);
// DBの変更を確定
context.SubmitChanges();
count++;
}
}
ts.Commit();
}
}
conn.Close();
}
</code></pre>
<p>これも処理速度アップとしては有効な手段でした。</p>
<h2 id="Sqlコマンドに変更する"><a href="#Sql%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B">Sqlコマンドに変更する</a></h2>
<p>データコンテキストを使って更新や追加を行うのも結構時間がかかるようなので、SQLクエリを直書きして実行するようにしてみます。</p>
<pre><code> using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite;version=3;synchronous=Normal;journal mode=Wal"))
{
using (DataContext context = new DataContext(conn))
{
using (var ts = conn.BeginTransaction())
{
foreach (Cat cat in list)
{
using (SQLiteCommand cmd = conn.CreateCommand())
{
// 対象のテーブルオブジェクトを取得
var table = context.GetTable<Cat>();
// データが存在するかどうか判定
if (table.SingleOrDefault(x => x.No == cat.No) == null)
{
String sql = @"INSERT INTO CAT (" +
" NO" +
", NAME" +
", SEX" +
", AGE" +
", KIND_CD" +
", FAVORITE" +
") VALUES (" +
cat.No +
"', '" + cat.Name +
"', '" + cat.Sex +
"', '" + cat.Age +
"', '" + cat.Kind +
"', '" + cat.Favorite + "')";
// データ追加
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
count++;
}
}
}
ts.Commit();
}
}
conn.Close();
}
</code></pre>
<p>こちらも勿論速度アップしました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>ちょっと殴り書きみたいな記事ですが、とりあえず上記のような対策を施すとひとまず何万件のインサートも問題なく実行できるかと思います。</p>
<p>もっと劇的に速度アップさせる必要がある場合は、<br />
登録するデータの存在確認をしないようにするといいと思います。<br />
(この場合はテーブル定義や、別で一時テーブルを用意するなど別途検討が必要となります)</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15233
2019-07-13T16:15:37+09:00
2019-07-13T16:15:37+09:00
https://crieit.net/posts/WPF-Orca
【WPF】Orcaデータベースエディタでバージョン体系を変更する方法
<p>セットアッププロジェクトを利用してインストーラーを作成すると、バージョン体系が 3段階となります。例えば 0.0.0。</p>
<p>普通は気にしなくてもいいかと思うんですが、アプリケーションなんかでバージョン情報を表示しようと思うと<br />
普通アセンブリから取得して表示するので、バージョンが一致しなくなってしまうんですよね。</p>
<p>ちなみにアセンブリに設定するバージョン体系は4段階となっています。</p>
<p>自動で一致させることが難しいっぽいので、インストーラー(msiファイル)を作成した後に無理やり合わせる方法を試してみました。</p>
<h2 id="Orcaのインストール"><a href="#Orca%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Orcaのインストール</a></h2>
<p>(Visual Studio をインストールする際に一緒にインストールされている可能性があります。)</p>
<p>環境によって場所が違うかもしれませんので、Orcaでファイル検索してみてください。</p>
<p>私の環境では次の場所に格納されていました。<br />
C:\Program Files (x86)\Windows Kits\8.0\bin\x86\Orca-x86_en-us.msi</p>
<p>どこにもない場合は、後述する「ダウンロード」を参照してください。</p>
<p>見つかった場合は、そのファイルを実行します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca002.jpg" alt="セットアップウィザード" /></p>
<p>セットアップウィザードが表示されるので、「Next」 ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca003.jpg" alt="ライセンス同意画面" /></p>
<p>ライセンス同意画面が表示されるので、「I Agree」にチェックし「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca004.jpg" alt="ユーザ情報設定画面" /></p>
<p>ユーザ情報設定画面が表示されるので、名前と所属を入力して「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca005.jpg" alt="インストールタイプの選択画面" /></p>
<p>インストールタイプの選択画面が表示されるので、「Custom」を選択して「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca006.jpg" alt="インストール先指定画面" /></p>
<p>インストール先指定画面が表示されるので、デフォルトのまま「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca007.jpg" alt="カスタムインストールチップス画面" /></p>
<p>カスタムインストールチップス画面が表示されるので、「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca008.jpg" alt="カスタムインストール設定画面" /></p>
<p>カスタムインストール設定画面が表示されるので、そのまま「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca009.jpg" alt="インストール開始画面" /></p>
<p>インストール開始画面が表示されるので、「Next」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca010.jpg" alt="インストール完了画面" /></p>
<p>インストール完了画面が表示されるので、「Finish」ボタンをクリックします。</p>
<p>以上でインストールは完了です。</p>
<h2 id="起動"><a href="#%E8%B5%B7%E5%8B%95">起動</a></h2>
<p>スタートメニューに「Orca」メニューが追加されているので、そこから起動します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca011.jpg" alt="Orca画面" /></p>
<p>上部メニューの「File」>「Open」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca012.jpg" alt="ファイル選択ダイアログ" /></p>
<p>ファイル選択ダイアログが表示されるので、対象の「msi」ファイルを選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca013.jpg" alt="バージョンの変更" /></p>
<p>「Table」から「Property」を選択し、表示された詳細から、「ProductVersion」の Value を変更します。</p>
<p>上部メニューの「File」>「Save」を選択して上書き保存すれば完了です。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca014.jpg" alt="プログラムと機能" /></p>
<p>「Windowsスタートメニュー」>「コントロールパネル」>「プログラムと機能」を見てみると<br />
バージョンが変更されていることが確認できます。</p>
<h2 id="Orcaのダウンロード"><a href="#Orca%E3%81%AE%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89">Orcaのダウンロード</a></h2>
<p>お使いの端末にインストーラーが存在しなかった場合、<br />
Microsoftのサイトからダウンロードしてください。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.microsoft.com/en-us/download/details.aspx?id=6510" target="_blank" rel="noopener noreferrer">https://www.microsoft.com/en-us/download/details.aspx?id=6510</a></p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca000.jpg" alt="ダウンロードサイト" /></p>
<p>Download ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/Orca001.jpg" alt="対象の選択" /></p>
<p>PSDK-amd64.exe にチェックし、「Next」ボタンをクリックします。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>本当はもっと便利な方法があればいいんですが、ちょっと情報が見つかりませんでした。</p>
<p>まあ何かのお役に立てれば。。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15226
2019-07-12T09:56:02+09:00
2019-07-12T09:56:02+09:00
https://crieit.net/posts/WPF-WebBrowser-PDF
【WPF】WebBrowser を使ってPDFファイルを表示してみる
<p>おはようございます。</p>
<p>今回は、WPFアプリでPDFを表示する方法のうち、WebBrowser でサクッとファイルを表示するのを試してみました。</p>
<p>画面に上部メニューを追加し、そこから呼び出せるように修正します。<br />
ヘルプやマニュアルなんかをアプリから表示する際にやったりしますよね。</p>
<p>プログラムは前回のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/11/01/post-2960/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】はてなアイコンにツールチップを表示する</a></p>
<h2 id="画面の追加"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E8%BF%BD%E5%8A%A0">画面の追加</a></h2>
<p>新規でPDFを表示するためのウィンドウを追加します。<br />
画像を取り忘れてしまいましたが、ソリューション・エクスプローラーから「追加」>「ウィンドウ」みたいな感じで出来るはずです。</p>
<h3 id="画面レイアウト"><a href="#%E7%94%BB%E9%9D%A2%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88">画面レイアウト</a></h3>
<p>PdfView.xaml</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.PdfView"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="PDFビュー" Width="1024" Height="768"
GlowBrush="{DynamicResource AccentColorBrush}"
BorderThickness="1"
Icon="/WpfApp1;component/Resource/Cat.ico"
WindowStartupLocation="CenterScreen" >
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid>
<WebBrowser x:Name="wb_manual" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="1,1,1,1"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<p>単純に WebBrowser を配置してスタイルを弄っただけです。</p>
<h3 id="コードビハインド"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%93%E3%83%8F%E3%82%A4%E3%83%B3%E3%83%89">コードビハインド</a></h3>
<p>PdfView.xaml.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
using System.Reflection;
namespace WpfApp1
{
/// <summary>
/// PdfView.xaml の相互作用ロジック
/// </summary>
public partial class PdfView : MetroWindow
{
public PdfView()
{
InitializeComponent();
Assembly mainAssembly = Assembly.GetExecutingAssembly();
String appDir = System.IO.Path.GetDirectoryName(mainAssembly.Location);
wb_manual.Navigate("file://" + appDir + "/Pdf/sample.pdf" + "#toolbar=1");
}
}
}
</code></pre>
<p> </p>
<p>実行ディレクトリを取得して、PDFのパスを絶対パスで指定します。<br />
また、ツールバーを表示したくなければ「#toolbar=1」を「#toolbar=0」に変更してください。</p>
<h2 id="PDFファイルの追加"><a href="#PDF%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%BF%BD%E5%8A%A0">PDFファイルの追加</a></h2>
<p>プロジェクト直下に「Pdf」フォルダ―を作成し、適当なPDFファイルを格納します。<br />
ファイル名は「sample.pdf」としました。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfPdf000.jpg" alt="出力設定" /></p>
<p>また、ファイルのプロパティを開き、常に実行ディレクトリにコピーするようにプロパティを変更します。</p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<h3 id="グリッドのレイアウト調整"><a href="#%E3%82%B0%E3%83%AA%E3%83%83%E3%83%89%E3%81%AE%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E8%AA%BF%E6%95%B4">グリッドのレイアウト調整</a></h3>
<p>MainWindow.xaml(抜粋)</p>
<pre><code> <Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
</code></pre>
<h3 id="メニュー追加"><a href="#%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC%E8%BF%BD%E5%8A%A0">メニュー追加</a></h3>
<p>MainWindow.xaml(抜粋)</p>
<pre><code> <Menu Style="{StaticResource menu-normal}" Background="#e7efff" Height="auto" Width="auto" Margin="0,0,0,20">
<MenuItem Header="ファイル(_F)" >
<MenuItem x:Name="menu_exit" Header="終了(_X)" Click="menu_exit_Click"/>
</MenuItem>
<MenuItem Header="その他(_O)">
<MenuItem x:Name="menu_pdfview" Header="サンプルPDF表示(_P)" Click="menu_pdfview_Click"/>
</MenuItem>
</Menu>
</code></pre>
<h3 id="スタイル定義の追加"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E5%AE%9A%E7%BE%A9%E3%81%AE%E8%BF%BD%E5%8A%A0">スタイル定義の追加</a></h3>
<p>StyleDic.xaml</p>
<pre><code> <Style x:Key="menu-normal" TargetType="Menu" >
<Setter Property="Background" Value="#ffeef1ff" />
</Style>
</code></pre>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<p>追加したメニューのクリックイベントの実装を追加します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 閉じるメニュークリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menu_exit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
/// <summary>
/// サンプルPDF表示メニュークリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menu_pdfview_Click(object sender, RoutedEventArgs e)
{
// ダイアログを表示
var win = new PdfView();
win.Owner = GetWindow(this);
win.ShowDialog();
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfPdf001.jpg" alt="起動後画面" /></p>
<p>上部にメニューが追加されました。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfPdf002.jpg" alt="閉じるメニュー" /></p>
<p>よくある閉じるメニュー。<br />
他に何も思いつきませんでした。。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfPdf003.jpg" alt="PDF表示メニュー" /></p>
<p>PDF表示用のメニューです。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfPdf005.jpg" alt="PDF表示" /></p>
<p>サンプルPFD表示メニューをクリックしてPDFを表示した画面です。<br />
無事に表示されました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>以前、何かの記事でも触れましたが<br />
Word で、「rand=(10,10)」みたいな文言を入力し、エンターを押すとランダムでサンプルドキュメントを作ることができます。</p>
<p>今回のPDFはその機能を使って作ったサンプルのドキュメントを、PDFとして保存したものとなります。</p>
<p>こういった便利なコマンドを知っていると、ちょっとした効率化ができますね。</p>
<p>WebBrowser はもちろん HTML も表示できるので他にも色々と応用することができそうですね。<br />
そのうちまた何か別のこともやってみたいと思います。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15217
2019-07-09T09:28:41+09:00
2019-07-09T09:28:41+09:00
https://crieit.net/posts/WPF-5d23dfb940064
【WPF】はてなアイコンを設置してツールチップでヘルプを表示する
<p>今回はツールチップによってヒントを表示するサンプルです。</p>
<p>本当は何も説明しなくてもいいユーザーインターフェースを目指すべきなんですが、なかなかそうもいかない場合もありますよね。</p>
<p>まあプラスアルファで付けるとそれはそれで喜ばれるものかもしれません。</p>
<p>プログラムは前回のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/10/14/post-2818/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】データグリッドにコンボボックスを表示する</a></p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<p>MainWindow.xaml</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.MainWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:p="clr-namespace:WpfApp1.Properties"
mc:Ignorable="d"
Title="一覧" Height="350" Width="530"
GlowBrush="{DynamicResource AccentColorBrush}"
Icon="/WpfApp1;component/Resource/Cat.ico"
BorderThickness="1"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid Height="350" Width="530" Margin="0,1,-10,-33">
<Grid.Resources>
<local:KindConverter x:Key="KindConv"/>
</Grid.Resources>
<Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />
<Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>
<Image Margin="54,15,0,0" Style="{StaticResource img-question}">
<ToolTipService.ToolTip>
<TextBlock Style="{StaticResource tkb-tooltip}" Text="{x:Static p:Resources.TL001}"/>
</ToolTipService.ToolTip>
</Image>
<TextBox x:Name="search_name" Margin="76,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>
<Image Margin="245,15,0,0" Style="{StaticResource img-question}">
<ToolTipService.ToolTip>
<TextBlock Style="{StaticResource tkb-tooltip}" Text="{x:Static p:Resources.TL002}"/>
</ToolTipService.ToolTip>
</Image>
<ComboBox x:Name="search_kind" Margin="275,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125" Style="{StaticResource MetroComboBox}" SelectedIndex="0" />
<Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75" Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>
<DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="40" />
<DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="False" Width="80"/>
<DataGridTemplateColumn IsReadOnly="True" Header="性別" CellStyle="{StaticResource dgc-combo}" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbGender" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid<span>}</span><span>}</span>, Path=DataContext.GenderList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" SelectedValuePath="Cd" SelectedValue="{Binding Sex}" Width="50" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Age, StringFormat=59:59}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="False" Width="40"/>
<DataGridTemplateColumn IsReadOnly="True" Header="種別" CellStyle="{StaticResource dgc-combo}" Width="110">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbKind" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid<span>}</span><span>}</span>, Path=DataContext.KindList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="KindName" SelectedValuePath="KindCd" SelectedValue="{Binding Kind}" Width="110" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="False" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock Style="{StaticResource tkb-tooltip}" Text="{x:Static p:Resources.TL003}"/>
</ToolTipService.ToolTip>
</Button>
</Grid>
</Mah:MetroWindow>
</code></pre>
<p>抜粋</p>
<pre><code> <Image Margin="54,15,0,0" Style="{StaticResource img-question}">
<ToolTipService.ToolTip>
<TextBlock Style="{StaticResource tkb-tooltip}" Text="{x:Static p:Resources.TL001}"/>
</ToolTipService.ToolTip>
</Image>
</code></pre>
<p>Imageタグの中に、ToolTipServiceのToolTipタグを入れ、更にテキストブロックでヒントを表示するようにしました。<br />
また、文言自体はリソースファイルから取得するようになっています。<br />
リソースを利用するために宣言部分に「xmlns:p」という属性を追加してあります。</p>
<h2 id="画像の追加"><a href="#%E7%94%BB%E5%83%8F%E3%81%AE%E8%BF%BD%E5%8A%A0">画像の追加</a></h2>
<p>![](https://www.doraxdora.com/wp-content/uploads/2017/11/questionMark-300x294.png" はてなアイコン</p>
<p>ハテナマークの画像を作成し、プロジェクト直下の「Resource」ディレクトリに追加します。<br />
(Inkscape というドローソフトでサクッと作りました)</p>
<h2 id="スタイル定義の追加"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E5%AE%9A%E7%BE%A9%E3%81%AE%E8%BF%BD%E5%8A%A0">スタイル定義の追加</a></h2>
<p>StyleDic.xaml(抜粋)</p>
<pre><code> <!-- テキストブロック:通常 -->
<Style x:Key="tkb-normal" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="FontSize" Value="14" />
</Style>
<Style x:Key="tkb-tooltip" TargetType="TextBlock" BasedOn="{StaticResource tkb-normal}">
<Setter Property="Background" Value="#fefbdf" />
<Setter Property="Padding" Value="3, 3, 3, 3" />
<Setter Property="Margin" Value="0" />
</Style>
<!-- イメージツールチップ -->
<Style x:Key="img-question" TargetType="Image">
<Setter Property="Source" Value="/Resource/questionMark.png" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="18" />
<Setter Property="Width" Value="18" />
<Setter Property="ToolTipService.ShowDuration" Value="30000" />
</Style>
</code></pre>
<h2 id="リソースの追加"><a href="#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E8%BF%BD%E5%8A%A0">リソースの追加</a></h2>
<p>ヒントで表示する文言をリソースに追加します。</p>
<p>Resources.resx</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTooltip000.jpg" alt="リソースの追加" /></p>
<p>文言を追加し、xamlからアクセスするためにアクセス修飾子を「public」に変更します。</p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTooltip001.jpg" alt="ツールチップ1" /></p>
<p>名前ラベルの横にあるハテナマークをマウスオーバーした表示です。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTooltip002.jpg" alt="ツールチップ2" /></p>
<p>こちらは種別ラベルの横のハテナマークをマウスオーバーした表示となります。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTooltip003.jpg" alt="ツールチップ3" /></p>
<p>ついでにボタンにもつけてみました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>簡単に実装できるうえ、スタイルを変更したり、表示時間を変更したりもできます。<br />
表示するコンポーネントをテキストブロック以外にも出来そうなので、カスタマイズ性抜群ですね。</p>
<p>興味のある方は色々試してみてください。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15211
2019-07-07T10:01:46+09:00
2019-07-07T10:01:46+09:00
https://crieit.net/posts/WPF-5d21447a573ab
【WPF】データグリッドにコンボボックス列を定義してリストを表示してみた
<p>今回はデータグリッドにコンボボックスを表示したいと思います。</p>
<p>チェックボックスと同様、デフォルトで「DataGridComboBoxColumn」がありますが、<br />
同じ理由(2回クリックしないと変更できない)で「DetaGridTemplateColumn」を利用したいと思います。</p>
<p>プログラムは次の記事のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/12/post-1997/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】データグリッドにチェックボックスを表示する</a></p>
<p><span style="color: #db2121;">※DBはSQLiteに変更してます</span></p>
<h2 id="スタイルの修正"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E4%BF%AE%E6%AD%A3">スタイルの修正</a></h2>
<p>StyleDic.xaml</p>
<pre><code> <!-- データグリッド:通常 -->
<Style x:Key="grid-normal" TargetType="DataGrid">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Grid.Row" Value="1" />
<Setter Property="HorizontalScrollBarVisibility" Value="Visible" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="IsReadOnly" Value="False" />
<Setter Property="CanUserAddRows" Value="False"/>
<Setter Property="AlternationCount" Value="1" />
<Setter Property="AlternatingRowBackground" Value="#B2CEEBF7" />
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="VerticalGridLinesBrush" Value="Gray" />
<Setter Property="HorizontalGridLinesBrush" Value="Gray" />
</Style>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Height" Value="25" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" Margin="4,4,4,4" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="dgc-combo" TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Height" Value="25" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" Margin="0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</code></pre>
<p>データグリッドを編集可能(行追加不可)にし、データグリッド内のコンボボックス用定義を追加。</p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<p>MainWindow.xaml</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.MainWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="一覧" Height="350" Width="530"
GlowBrush="{DynamicResource AccentColorBrush}"
Icon="/WpfApp1;component/Resource/Cat.ico"
BorderThickness="1"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid Height="350" Width="530" Margin="0,1,-10,-33">
<Grid.Resources>
<local:KindConverter x:Key="KindConv"/>
</Grid.Resources>
<Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />
<Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="search_name" Margin="56,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>
<ComboBox x:Name="search_kind" Margin="252,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125" Style="{StaticResource MetroComboBox}" SelectedIndex="0" />
<Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75" Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>
<DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="40" />
<DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="True" Width="80"/>
<DataGridTemplateColumn IsReadOnly="True" Header="性別" CellStyle="{StaticResource dgc-combo}" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbGender" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid<span>}</span><span>}</span>, Path=DataContext.GenderList, Mode=OneWay}"
DisplayMemberPath="Name" SelectedValuePath="Cd" SelectedValue="{Binding Sex}" Width="50"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="True" Width="40"/>
<DataGridTextColumn Binding="{Binding Kind, Converter={StaticResource KindConv<span>}</span><span>}</span>" ClipboardContentBinding="{x:Null}" Header="種別" IsReadOnly="True" Width="110"/>
<DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="True" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<p>「性別」列を「DataGridTemplateColumn」に変更し、コンボボックスを設置。</p>
<p>ポイントは次のプロパティ</p>
<pre><code>ItemsSource
</code></pre>
<p>コンボボックスの表示内容となるリスト<br />
コードビハインドにて、DataContextに設定したリストを指定<br />
DisplayMemberPath<br />
バインドされたクラスの表示するメンバーを指定<br />
SelectedValuePath<br />
バインドされたクラスの値となるメンバーを指定<br />
SelectedValue<br />
データグリッドにバインドされたリストのメンバーを指定<br />
この項目が紐付きとなる</p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="新規クラス追加"><a href="#%E6%96%B0%E8%A6%8F%E3%82%AF%E3%83%A9%E3%82%B9%E8%BF%BD%E5%8A%A0">新規クラス追加</a></h3>
<p>コンボボックスに設定するためのクラスを作成</p>
<p>Gender.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace WpfApp1
{
/// <summary>
/// 性別クラス
/// </summary>
public class Gender
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="cd"></param>
/// <param name="name"></param>
public Gender(int cd, String name)
{
Cd = cd;
Name = name;
}
/// <summary>
/// 性別コード
/// </summary>
public int Cd { get; set; }
/// <summary>
/// 性別名
/// </summary>
public String Name { get; set; }
}
}
</code></pre>
<h3 id="コードビハインドの修正"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%93%E3%83%8F%E3%82%A4%E3%83%B3%E3%83%89%E3%81%AE%E4%BF%AE%E6%AD%A3">コードビハインドの修正</a></h3>
<p>下記をグローバルスコープで定義</p>
<p>MainWindow.xaml.cs(抜粋)</p>
<pre><code> /// <summary>
/// データグリッド:性別コンボの項目リスト
/// </summary>
public List<Gender> GenderList { set; get; }
</code></pre>
<p>起動時にデータグリッド内のコンボボックス用リストを作成して設定</p>
<p>MainWindow.xaml.cs(抜粋)</p>
<pre><code> public MainWindow()
{
InitializeComponent();
// データグリッドに表示するコンボの項目を設定
GenderList = new List<Gender>();
GenderList.Add(new Gender(1, "♂"));
GenderList.Add(new Gender(2, "♀"));
this.DataContext = this;
// SampleDb.sqlite を作成(存在しなければ)
using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
{
// データベースに接続
conn.Open();
// コマンドの実行
using (var command = conn.CreateCommand())
{
// テーブルが存在しなければ作成する
// 種別マスタ
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE IF NOT EXISTS MSTKIND (");
sb.Append(" KIND_CD NCHAR NOT NULL");
sb.Append(" , KIND_NAME NVARCHAR");
sb.Append(" , primary key (KIND_CD)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
// 猫テーブル
sb.Clear();
sb.Append("CREATE TABLE IF NOT EXISTS TBLCAT (");
sb.Append(" NO INT NOT NULL");
sb.Append(" , NAME NVARCHAR NOT NULL");
sb.Append(" , SEX NVARCHAR NOT NULL");
sb.Append(" , AGE INT DEFAULT 0 NOT NULL");
sb.Append(" , KIND_CD NCHAR DEFAULT 0 NOT NULL");
sb.Append(" , FAVORITE NVARCHAR");
sb.Append(" , primary key (NO)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
}
// 種別マスタを取得してコンボボックスに設定する
using (DataContext con = new DataContext(conn))
{
// データを取得
Table<Kind> tblCat = con.GetTable<Kind>();
IQueryable<Kind> result = from x in tblCat orderby x.KindCd select x;
// 最初の要素は「指定なし」とする
Kind empty = new Kind();
empty.KindCd = "";
empty.KindName = "指定なし";
var list = result.ToList();
list.Insert(0, empty);
// コンボボックスに設定
this.search_kind.ItemsSource = list;
this.search_kind.DisplayMemberPath = "KindName";
}
// 切断
conn.Close();
}
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/DataGridCombobox000.jpg" alt="起動後の画面" /></p>
<p>起動直後、「性別」がコンボボックスになってますね。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/DataGridCombobox001.jpg" alt="コンボボックスの選択" /></p>
<p>クリックすると、コンボボックスが展開されて変更することができます。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>データグリッドにコンボボックスを表示する方法は色々ありますが、<br />
とりあえずこんな感じで落ち着きました。</p>
<p>今後他のコントロールも試していきたいと思います。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15204
2019-07-05T14:32:46+09:00
2019-07-05T14:32:46+09:00
https://crieit.net/posts/WPF-5d1ee0fed8904
【WPF】カスタム動作を利用してアンインストール時にタスクを削除する
<p>昨日に引き続きですが、<br />
アプリでタスク登録した場合はアンインストール時に削除しないと<br />
存在しないバッチなんかを永遠に実行することになりかねないですよね。</p>
<p>ということで、アプリをアンインストールした際にタスクを削除してみます。</p>
<p>一応、前回の記事はこちら。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/10/07/post-2680/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】Windowsのタスクスケジューラにタスクを登録する</a></p>
<h2 id="削除用スクリプトの作成"><a href="#%E5%89%8A%E9%99%A4%E7%94%A8%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">削除用スクリプトの作成</a></h2>
<p>下記、2つのファイルをプロジェクトのフォルダに配置します。</p>
<p>(カスタム動作からバッチファイルを直接呼び出すことができないため、<br />
バッチを呼び出すVBScriptも作成します。)</p>
<p>taskDel.bat</p>
<pre><code> @echo off
SET LOGF=taskDelete.log
echo [%DATE% %TIME%] タスクスケジュール設定を削除します。 > %LOGF%
echo. >> %LOGF%
echo %CD% >> %LOGF%
schtasks /delete /TN DORADORA\WpfApp1(自動実行タスク) /F >> %LOGF%
echo. >> %LOGF%
echo [%DATE% %TIME%] タスクスケジュール設定を削除しました。 >> %LOGF%
exit
</code></pre>
<p>taskDel.vbs</p>
<pre><code>Option Explicit
Dim intReturn
Dim ws
Set ws = CreateObject("Wscript.Shell")
intReturn = ws.run("cmd /c " & Property("CustomActionData") & "taskDel.bat", 0)
</code></pre>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction000.jpg" alt="バッチ、スクリプトの追加" /></p>
<h2 id="セットアッププロジェクトの設定"><a href="#%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A">セットアッププロジェクトの設定</a></h2>
<h3 id="バッチ、スクリプトの配置"><a href="#%E3%83%90%E3%83%83%E3%83%81%E3%80%81%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E9%85%8D%E7%BD%AE">バッチ、スクリプトの配置</a></h3>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction001.jpg" alt="ファイルシステムを表示" /></p>
<p>パッケージ・エクスプローラーからセットアッププロジェクトを右クリックし、<br />
「View」>「ファイル システム」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction002.jpg" alt="ファイル選択" /></p>
<p>「Application Folder」を右クリックし、「Add」>「ファイル」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction03jpg" alt="バッチ、スクリプトの選択" /></p>
<p>プロジェクトに追加した、「taskDel.bat」、「taskDel.vbs」を選択して「開く」ボタンをクリックします。</p>
<h3 id="カスタム動作の設定"><a href="#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E5%8B%95%E4%BD%9C%E3%81%AE%E8%A8%AD%E5%AE%9A">カスタム動作の設定</a></h3>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction004.jpg" alt="カスタム動作の表示" /></p>
<p>パッケージ・エクスプローラーからセットアッププロジェクトを右クリックし、<br />
「View」>「カスタム動作」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction005-1.jpg" alt="カスタム動作の追加" /></p>
<p>「Uninstall」を右クリックし、「カスタム動作の追加」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction006.jpg" alt="スクリプトを選択" /></p>
<p>項目選択ダイアログが表示されるので<br />
「Application Folder」から、「taskDel.vbs」を選択して「OK」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction007.jpg" alt="プロパティ" /></p>
<p>追加した「taskDel.vbs」のプロパティを開き、<br />
「CustomActionData」に、「 [TARGETDIR] 」を入力します。</p>
<p>以上でカスタム動作の設定は完了です。</p>
<h3 id="カスタム動作の種類"><a href="#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E5%8B%95%E4%BD%9C%E3%81%AE%E7%A8%AE%E9%A1%9E">カスタム動作の種類</a></h3>
<p>種類<br />
説明</p>
<p>Install(インストール)<br />
全てのファイルがインストールされた後に実行されます。</p>
<p>Commit(確定)<br />
インストールが問題なく終了した後に実行されます。</p>
<p>Rollback(ロールバック)<br />
インストール中にエラーが発生し、ロールバックされた後に実行されます。</p>
<p>Uninstall(アンインストール)<br />
アンインストールされた後に実行されます。</p>
<h2 id="インストール"><a href="#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">インストール</a></h2>
<p>セットアッププロジェクトをビルドし、<br />
作成されたモジュールからアプリケーションをインストールし、一度起動します。<br />
(タスク登録処理が実行される)</p>
<h2 id="アンインストール"><a href="#%E3%82%A2%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">アンインストール</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction008.jpg" alt="アンインストール" /></p>
<p>「コントロールパネル」>「すべてのコントロールパネル項目」>「プログラムと機能」を開き、<br />
インストールされている「WpfApp1」を右クリックし、「アンインストール」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction009.jpg" alt="確認ダイアログ" /></p>
<p>アンインストール確認ダイアログが表示される場合は「OK」ボタンをクリックします。</p>
<p>アンインストールが完了したら、<br />
タスクスケジューラを起動してタスクの確認をします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfUnInstallAction010.jpg" alt="タスクスケジューラー" /></p>
<p>無事にタスクが削除されていることが確認できました。</p>
<p>何かのお役に立てれば。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15201
2019-07-04T10:27:15+09:00
2019-07-04T10:27:15+09:00
https://crieit.net/posts/WPF-Windows
【WPF】Windowsのタスクスケジューラにタスクを登録する
<p>Windows のソフトであれば、<br />
タスクスケジューラを使って何かしたいってこと、あると思います。</p>
<p>のでやってみました。</p>
<p>プログラムは前回のものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/09/05/post-2364/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】Oracleに接続してデータ操作(追加、更新、削除)してみる</a></p>
<h2 id="参照の追加"><a href="#%E5%8F%82%E7%85%A7%E3%81%AE%E8%BF%BD%E5%8A%A0">参照の追加</a></h2>
<p>プログラムからタスクスケジューラを操作するためのライブラリを追加します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTaskScheduler000.jpg" alt="参照の追加" /></p>
<p>パッケージ・エクスプローラーの「参照」を右クリックし「参照の追加」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTaskScheduler001.jpg" alt="ライブラリの追加" /></p>
<p>「COM」を選択し、「task」でフィルタリング、<br />
「TaskScheduler 1.1 Type Library」にチェックをして「OK」ボタンをクリックします。</p>
<h2 id="新規クラス作成"><a href="#%E6%96%B0%E8%A6%8F%E3%82%AF%E3%83%A9%E3%82%B9%E4%BD%9C%E6%88%90">新規クラス作成</a></h2>
<p>タスク登録用のクラスを追加します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTaskScheduler002.jpg" alt="クラスの追加" /></p>
<p>パッケージ・エクスプローラーでプロジェクトを右クリック、<br />
「追加」>「クラス」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTaskScheduler003.jpg" alt="クラス名の入力" /></p>
<p>名前に「TaskManager.cs」と入力して「追加」ボタンをクリックします。</p>
<p>TaskManager.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using TaskScheduler;
namespace WpfApp1
{
class TaskManager
{
public static void RegistTask()
{
ITaskService taskservice = null;
try
{
taskservice = new TaskScheduler.TaskScheduler();
taskservice.Connect(null, null, null, null);
ITaskFolder rootfolder = null;
try
{
// アセンブリ情報取得
Assembly mainAssembly = Assembly.GetExecutingAssembly();
// ソフトウェア名
string appName = "-";
object[] AppNameArray = mainAssembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if ((AppNameArray != null) && (AppNameArray.Length > 0))
{
appName = ((AssemblyTitleAttribute)AppNameArray[0]).Title;
}
// 追加フォルダを指定する
rootfolder = taskservice.GetFolder("\\");
String path = "\\DORADORA\\" + appName + "(自動実行タスク)";
// 新規登録用のタスク定義
ITaskDefinition taskDefinition = taskservice.NewTask(0);
// RegistrationInfoプロパティ
IRegistrationInfo registrationInfo = taskDefinition.RegistrationInfo;
// Actionsプロパティ
IActionCollection actionCollection = taskDefinition.Actions;
IExecAction execAction = (IExecAction)actionCollection.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
// Triggersプロパティ
ITriggerCollection triggerCollection = taskDefinition.Triggers;
ITimeTrigger timeTrigger = (ITimeTrigger)triggerCollection.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_TIME);
// Settingsプロパティ
ITaskSettings taskSettings = taskDefinition.Settings;
/** 全般タブ */
// 作成者
registrationInfo.Author = "DORADORA";
// 説明
registrationInfo.Description = "タスク登録のサンプル";
// 主要な設定
IPrincipal principal = taskDefinition.Principal;
// タスクの実行時に使うユーザアカウント
principal.UserId = Environment.UserDomainName + "\\" + Environment.UserName;
// ユーザがログオンしているかどうかにかかわらず実行する(パスワードを保存しない(チェックあり))
principal.LogonType = _TASK_LOGON_TYPE.TASK_LOGON_S4U;
// 最上位特権で実行する
//principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
// 表示しない
taskSettings.Hidden = true;
// 優先度
taskSettings.Priority = 6;
/** トリガタブ */
// 開始
timeTrigger.StartBoundary = "2017-10-02T00:00:00";
// 繰り返し間隔
timeTrigger.Repetition.Interval = "PT1H";
// 有効
timeTrigger.Enabled = true;
/** 操作タブ */
// 実行フォルダ取得
String appDir = System.IO.Path.GetDirectoryName(mainAssembly.Location);
// プログラム/スクリプト
execAction.Path = appDir + "\\taskSample.vbs";
// 引数の追加(オプション)
//execAction.Arguments = "引数";
// 開始(オプション)
execAction.WorkingDirectory = appDir;
try
{
rootfolder.RegisterTaskDefinition(path,
taskDefinition,
(int)_TASK_CREATION.TASK_CREATE_OR_UPDATE,
null,
null,
_TASK_LOGON_TYPE.TASK_LOGON_NONE,
null);
}
catch (System.UnauthorizedAccessException e)
{
throw e;
}
catch (System.Exception e)
{
throw e;
}
}
finally
{
if (rootfolder != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(rootfolder);
}
}
finally
{
if (taskservice != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(taskservice);
}
}
}
}
</code></pre>
<p>今回は単純に起動してから<br />
60分(1時間)毎に繰り返し実行するタスクを登録するようにしました。</p>
<h2 id="トリガーの種類"><a href="#%E3%83%88%E3%83%AA%E3%82%AC%E3%83%BC%E3%81%AE%E7%A8%AE%E9%A1%9E">トリガーの種類</a></h2>
<p> </p>
<p>インターフェース<br />
説明</p>
<p>IEventTrigger<br />
システムイベントが発生したタイミングで開始する</p>
<p>ITimeTrigger<br />
特定の日時に開始する</p>
<p>IDailyTrigger<br />
日次スケジュールに基づいてタスクを開始するタスクは毎日、1日おき、3日おきなど特定の時刻に開始されます。</p>
<p>IWeeklyTrigger<br />
週単位のスケジュールに基づいてタスクを開始する</p>
<p>IMonthlyTrigger<br />
毎月のスケジュールに基づいてタスクを開始する</p>
<p>IMonthlyDOWTrigger<br />
月曜日の曜日スケジュールでタスクを開始する</p>
<p>IIdleTrigger<br />
コンピュータがアイドル状態になったときにタスクを開始する</p>
<p>IRegistrationTrigger<br />
タスクが登録されたときにタスクを開始する</p>
<p>IBootTrigger<br />
システムの起動時にタスクを開始する</p>
<p>ILogonTrigger<br />
ユーザーがログオンしたときにタスクを開始する</p>
<p>ISessionStateChangeTrigger<br />
コンソールの接続または切断、リモート接続または切断、またはワークステーションのロックまたはロック解除通知のタスクをトリガーします</p>
<p>各トリガーの使用方法は長くなるので割愛させてください。</p>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="起動時にタスク登録を実行する"><a href="#%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E3%82%BF%E3%82%B9%E3%82%AF%E7%99%BB%E9%8C%B2%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B">起動時にタスク登録を実行する</a></h3>
<p>コンストラクタに次の記述を追加します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code>// タスクを登録
TaskManager.RegistTask();
</code></pre>
<h2 id="実行するバッチの配置"><a href="#%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%83%90%E3%83%83%E3%83%81%E3%81%AE%E9%85%8D%E7%BD%AE">実行するバッチの配置</a></h2>
<p>下記のファイルを作成し、実行フォルダに配置します。</p>
<p>taskSample.bat</p>
<pre><code> @echo off
echo %DATE% %TIME% タスク実行 > task.log
exit /0
</code></pre>
<p>taskSample.vbs</p>
<pre><code> Option Explicit
Dim intReturn
Dim ws
Set ws = CreateObject("Wscript.Shell")
intReturn = ws.run("cmd /c taskSample.bat", 0)
WScript.Quit(intReturn)
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfTaskScheduler004.jpg" alt="タスクスケジューラー" /></p>
<p>タスクスケジューラ―を起動すると、無事にタスクが登録されているのが確認できました。</p>
<p>今回はここまで。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15193
2019-07-03T09:45:14+09:00
2019-07-03T09:45:14+09:00
https://crieit.net/posts/WPF-Oracle-DataAccess
【WPF】「Oracle.DataAccess」を利用してデータ操作(追加、更新、削除)してみる
<p>引き続き、Oracle.DataAccess を使ってデータの登録、更新、削除をしてみます。</p>
<p>前回の記事はこちら。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/09/02/post-2322/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】「Oracle.DataAccess」を利用して取得したデータを DataGrid に表示してみる</a></p>
<p>今回も、Entity Framework などは使わずに OracleCommand で実装していますので、サクッと書きます。</p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="登録更新フォーム表示時の処理"><a href="#%E7%99%BB%E9%8C%B2%E6%9B%B4%E6%96%B0%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E8%A1%A8%E7%A4%BA%E6%99%82%E3%81%AE%E5%87%A6%E7%90%86">登録更新フォーム表示時の処理</a></h3>
<p>SubWindow.xaml.cs</p>
<pre><code> public SubWindow(CatModel SelectedCat)
{
InitializeComponent();
// データを取得
// 種別マスタを取得してコンボボックスに設定する
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
// データを取得
OracleCommand cmd = new OracleCommand("SELECT * FROM MSTKIND", conn);
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
// コンボボックスに値を設定
List<Kind> sources = new List<Kind>();
Kind k = new Kind();
k.KindCd = "00";
k.KindName = "指定なし";
sources.Add(k);
foreach (DataRow row in dt.Rows)
{
k = new Kind();
k.KindCd = row["KIND_CD"].ToString();
k.KindName = row["KIND_NAME"].ToString();
sources.Add(k);
}
// コンボボックスに設定
this.cmb_kind.ItemsSource = sources;
this.cmb_kind.DisplayMemberPath = "KindName";
if (SelectedCat == null)
{
// 追加処理の場合
this.Title = "追加";
this.btn_add.Visibility = Visibility.Visible;
this.btn_mod.Visibility = Visibility.Collapsed;
}
else
{
this.SelectedCat = SelectedCat;
// 更新処理の場合
this.Title = "更新";
this.btn_add.Visibility = Visibility.Collapsed;
this.btn_mod.Visibility = Visibility.Visible;
// 値の設定
this.txt_name.Text = SelectedCat.Name;
foreach (ComboBoxItem i in this.cmb_sex.Items)
{
if (i.Content.ToString().Trim() == SelectedCat.Sex.Trim())
{
this.cmb_sex.SelectedItem = i;
}
}
this.txt_age.Text = SelectedCat.Age.ToString();
foreach (Kind kind in sources)
{
if (kind.KindCd == SelectedCat.Kind)
{
this.cmb_kind.SelectedItem = kind;
break;
}
}
this.txt_favorite.Text = SelectedCat.Favorite;
}
}
}
</code></pre>
<h3 id="追加処理"><a href="#%E8%BF%BD%E5%8A%A0%E5%87%A6%E7%90%86">追加処理</a></h3>
<p>SubWindow.xaml.cs</p>
<pre><code> private void btn_add_Click(object sender, RoutedEventArgs e)
{
this.IsCancel = false;
// データを追加する
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
// シーケンス列としていないので、
// 最初に件数を取得して No を計算する
OracleCommand cmd = new OracleCommand("SELECT COUNT(*) FROM TBLCAT", conn);
decimal cnt = (decimal)cmd.ExecuteScalar();
// クエリ作成
String query = "INSERT INTO TBLCAT VALUES ("
+ ++cnt
+ ", '" + this.txt_name.Text + "'"
+ ", '" + (this.cmb_sex.SelectedItem as ComboBoxItem).Content + "'"
+ ", " + this.txt_age.Text
+ ", '" + (this.cmb_kind.SelectedItem as Kind).KindCd + "'"
+ ", '" + this.txt_favorite.Text + "')";
// クエリ実行
cmd = new OracleCommand(query, conn);
cmd.ExecuteNonQuery();
conn.Close();
MessageBox.Show("データを追加しました。");
}
this.Close();
}
</code></pre>
<h3 id="更新処理"><a href="#%E6%9B%B4%E6%96%B0%E5%87%A6%E7%90%86">更新処理</a></h3>
<p>SubWindow.xaml.cs</p>
<pre><code> private void btn_mod_Click(object sender, RoutedEventArgs e)
{
this.IsCancel = false;
// データを更新する
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
// クエリ作成
String query = "UPDATE TBLCAT SET"
+ " NAME = '" + this.txt_name.Text + "'"
+ ", SEX = '" + (this.cmb_sex.SelectedItem as ComboBoxItem).Content + "'"
+ ", AGE = " + this.txt_age.Text
+ ", KIND_CD = '" + (this.cmb_kind.SelectedItem as Kind).KindCd + "'"
+ ", FAVORITE = '" + this.txt_favorite.Text + "' "
+ "WHERE NO = " + SelectedCat.No;
// クエリ実行
OracleCommand cmd = new OracleCommand(query, conn);
cmd.ExecuteNonQuery();
conn.Close();
MessageBox.Show("データを更新しました。");
}
this.Close();
}
</code></pre>
<h3 id="削除処理"><a href="#%E5%89%8A%E9%99%A4%E5%87%A6%E7%90%86">削除処理</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> private void del_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("削除ボタンクリック");
// データを削除する
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
int checkCount = 0;
List<CatModel> list = this.dataGrid.ItemsSource as List<CatModel>;
String query;
foreach (CatModel cat in list)
{
if (cat.IsChecked)
{
checkCount++;
// クエリ作成
query = "DELETE FROM TBLCAT WHERE NO = " + cat.No;
// クエリ実行
OracleCommand cmd = new OracleCommand(query, conn);
cmd.ExecuteNonQuery();
}
}
conn.Close();
if (checkCount == 0)
{
MessageBox.Show("削除対象にチェックがされていません。");
return;
}
}
// データ再検索
searchData();
MessageBox.Show("データを削除しました。");
}
</code></pre>
<p> </p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>そのうちまた違った方法で試してみたいと思いますが、Oracleはとりあえずここまでです。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15187
2019-07-02T11:15:57+09:00
2019-07-02T11:15:57+09:00
https://crieit.net/posts/WPF-Oracle-DataAccess-DataGrid
【WPF】「Oracle.DataAccess」を利用して取得したデータを DataGrid に表示してみる
<p>今回は、Oracle.DataAccess を使ってデータを検索、データグリッドに表示してみます。<br />
プログラムは前回までのものを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/19/post-2109/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】別ウィンドウに値を受け渡して、データを更新できるようにしてみた</a></p>
<p>今までと同様、Entity Framework 、LINQ を利用してやってみようと思ったのですが、<br />
ちょっと調べきれなかったのでひとまず DataTable を利用して自力でマッピングするといった感じになってしまいました。</p>
<p>EFとLINQについてはそのうち時間がある時に。。</p>
<h2 id="参照の追加"><a href="#%E5%8F%82%E7%85%A7%E3%81%AE%E8%BF%BD%E5%8A%A0">参照の追加</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/09/WpfOracle000.jpg" alt="参照の追加" /></p>
<p>パッケージ・エクスプローラーの「参照」を右クリックし、「参照の追加」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/09/WpfOracle001.jpg" alt="参照マネージャー" /></p>
<p>参照マネージャー画面が表示されるので、「参照」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/09/WpfOracle002.jpg" alt="ファイル選択ダイアログ" /></p>
<p>ファイル選択ダイアログが表示されるので、端末にインストールした「Oracle」から<br />
Oracle.DataAccess.dll ファイルを指定します。</p>
<p>デフォルトであれば、下記のディレクトリにあります。<br />
c:\oraclexe\app\oracle\product\11.2.0\server\odp.net\bin\4\</p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="宣言の追加"><a href="#%E5%AE%A3%E8%A8%80%E3%81%AE%E8%BF%BD%E5%8A%A0">宣言の追加</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code>using System.Data;
using Oracle.DataAccess.Client;
</code></pre>
<h3 id="接続処理の変更"><a href="#%E6%8E%A5%E7%B6%9A%E5%87%A6%E7%90%86%E3%81%AE%E5%A4%89%E6%9B%B4">接続処理の変更</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code>//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
</code></pre>
<h3 id="初期表示時の処理を修正"><a href="#%E5%88%9D%E6%9C%9F%E8%A1%A8%E7%A4%BA%E6%99%82%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E4%BF%AE%E6%AD%A3">初期表示時の処理を修正</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> public MainWindow()
{
InitializeComponent();
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
// データを取得
OracleCommand cmd = new OracleCommand("SELECT * FROM MSTKIND", conn);
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
// コンボボックスに値を設定
List<Kind> sources = new List<Kind>();
Kind k = new Kind();
k.KindCd = "";
k.KindName = "指定なし";
sources.Add(k);
foreach (DataRow row in dt.Rows)
{
k = new Kind();
k.KindCd = row["KIND_CD"].ToString();
k.KindName = row["KIND_NAME"].ToString();
sources.Add(k);
}
this.search_kind.ItemsSource = sources;
this.search_kind.DisplayMemberPath = "KindName";
conn.Close();
}
}
</code></pre>
<h3 id="検索処理の修正"><a href="#%E6%A4%9C%E7%B4%A2%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">検索処理の修正</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 検索処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcess(object sender, DoWorkEventArgs e)
{
// 時間のかかるようにする
System.Threading.Thread.Sleep(3000);
// 猫データマスタを取得してコンボボックスに設定する
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
String searchName = (e.Argument as Object[])[0] as String;
String searchKind = (e.Argument as Object[])[1] as String;
// データを取得
String sql = "SELECT * FROM TBLCAT";
String where = "";
if (searchName != "")
{
where = " WHERE NAME LIKE '" + searchName + "%'";
}
if (searchKind != "")
{
if (where != "")
{
where += " AND";
}
else
{
where = " WHERE";
}
where += " KIND_CD = '" + searchKind + "'";
}
sql += where;
OracleCommand cmd = new OracleCommand(sql, conn);
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
List<CatModel> sources = new List<CatModel>();
foreach (DataRow row in dt.Rows)
{
CatModel c = new CatModel();
c.IsChecked = false;
String no = row["NO"].ToString();
c.No = int.Parse(row["NO"].ToString());
c.Name = row["NAME"].ToString();
c.Sex = row["SEX"].ToString();
c.Age = int.Parse(row["AGE"].ToString());
c.Kind = row["KIND_CD"].ToString();
c.Favorite = row["FAVORITE"].ToString();
sources.Add(c);
}
e.Result = sources;
}
}
</code></pre>
<h3 id="コンバーターの修正"><a href="#%E3%82%B3%E3%83%B3%E3%83%90%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AE%E4%BF%AE%E6%AD%A3">コンバーターの修正</a></h3>
<pre><code> /// <summary>
/// データ変換処理
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
using (var conn = new OracleConnection("Data Source=localhost;User Id=USER01;Password=USER01;"))
{
conn.Open();
// データを取得
OracleCommand cmd = new OracleCommand("SELECT * FROM MSTKIND WHERE KIND_CD = '" + value + "'", conn);
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
String ret = "";
if (dt.Rows.Count == 1)
{
ret = dt.Rows[0]["KIND_NAME"].ToString();
}
conn.Close();
return ret;
}
}
</code></pre>
<p> </p>
<p>ひとまずこれで検索はできるようになるはずです。</p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/09/WpfOracle004.jpg" alt="起動後の画面" /></p>
<p>検索ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/09/WpfOracle005.jpg" alt="検索後の画面" /></p>
<p>無事に検索してデータが表示されました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>例によって、登録・更新・削除はまた次回ということで。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15185
2019-07-01T15:42:43+09:00
2019-07-01T15:42:43+09:00
https://crieit.net/posts/WPF-5d19ab6374dd0
【WPF】別ウィンドウに値を受け渡してデータを更新できるようにしてみた
<p>引き続き、モーダル表示した子ウィンドウの話です。</p>
<p>こういった画面を作る際に必要となるのが、親画面から子画面(逆もまたしかり)へのデータ渡しですよね。</p>
<p>ということで、今回はデータの修正を別ウィンドウで行うように修正するついでに、親から子へデータを渡す方法を試してみます。</p>
<p>プログラムは前回のものを。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/18/post-2073/" target="_blank" rel="noopener" data-blogcard="1">【WPF】登録画面を作成して別ウィンドウのモーダル表示をやってみた。</a></p>
<h2 id="画面の変更"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E5%A4%89%E6%9B%B4">画面の変更</a></h2>
<p>SubWindow.xaml<br />
更新ボタンを追加し、デフォルトを非表示状態にする。</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.SubWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="追加" Height="300" Width="300"
GlowBrush="{DynamicResource AccentColorBrush}"
Icon="/WpfApp1;component/Resource/Cat.ico"
BorderThickness="1"
WindowStartupLocation="CenterOwner"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}" RenderTransformOrigin="0.522,0.893"/>
<TextBox x:Name="txt_name" Margin="61,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Style="{StaticResource MetroTextBox}"/>
<Label Content="性別:" Margin="10,54,0,0" Style="{StaticResource lb-normal}"/>
<ComboBox x:Name="cmb_sex" HorizontalAlignment="Left" Margin="61,54,0,0" VerticalAlignment="Top" Width="50">
<ComboBoxItem Content="♂" HorizontalAlignment="Left" Width="50"/>
<ComboBoxItem Content="♀" HorizontalAlignment="Left" Width="50"/>
</ComboBox>
<ComboBox x:Name="cmb_kind" HorizontalAlignment="Left" Margin="61,140,0,0" VerticalAlignment="Top" Width="150"/>
<Label Content="年齢:" Margin="10,98,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="txt_age" Margin="61,98,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="10,143,0,0" Style="{StaticResource lb-normal}"/>
<Label Content="好物:" Margin="10,186,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="txt_favorite" Margin="61,186,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Style="{StaticResource MetroTextBox}"/>
<Button x:Name="btn_cansel" Content="キャンセル" HorizontalAlignment="Left" Margin="125,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_cansel_Click"/>
<Button x:Name="btn_add" Content="追加" HorizontalAlignment="Left" Margin="205,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_add_Click"/>
<Button x:Name="btn_mod" Content="更新" HorizontalAlignment="Left" Margin="205,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_mod_Click" Visibility="Collapsed"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="コンストラクタに引数を追加"><a href="#%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF%E3%81%AB%E5%BC%95%E6%95%B0%E3%82%92%E8%BF%BD%E5%8A%A0">コンストラクタに引数を追加</a></h3>
<p>親画面から値を受け取るために引数を追加します。<br />
SubWindow.xaml.cs</p>
<pre><code> public SubWindow()
を
public SubWindow(CatModel SelectedCat)
に変更する
</code></pre>
<h3 id="グローバル変数の追加"><a href="#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E5%A4%89%E6%95%B0%E3%81%AE%E8%BF%BD%E5%8A%A0">グローバル変数の追加</a></h3>
<p>更新時に参照するためにグローバルな変数に受け取ったデータを設定します。<br />
SubWindow.xaml.cs</p>
<pre><code>public CatModel SelectedCat { set; get; }
</code></pre>
<h3 id="初期化処理の修正"><a href="#%E5%88%9D%E6%9C%9F%E5%8C%96%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">初期化処理の修正</a></h3>
<p>追加、更新でボタンの表示切替、及び画面へのデータ設定を行うようにします。<br />
SubWindow.xaml.cs</p>
<pre><code> public SubWindow(CatModel SelectedCat)
{
InitializeComponent();
// データを取得
// 種別マスタを取得してコンボボックスに設定する
using (var context = new PgDbContext())
{
var mstKind = context.Kinds;
IQueryable<Kind> result = from x in mstKind orderby x.KindCd select x;
var list = result.ToList();
// コンボボックスに設定
this.cmb_kind.ItemsSource = list;
this.cmb_kind.DisplayMemberPath = "KindName";
if (SelectedCat == null)
{
// 追加処理の場合
this.Title = "追加";
this.btn_add.Visibility = Visibility.Visible;
this.btn_mod.Visibility = Visibility.Collapsed;
}
else
{
this.SelectedCat = SelectedCat;
// 更新処理の場合
this.Title = "更新";
this.btn_add.Visibility = Visibility.Collapsed;
this.btn_mod.Visibility = Visibility.Visible;
// 値の設定
this.txt_name.Text = SelectedCat.Name;
foreach (ComboBoxItem i in this.cmb_sex.Items)
{
if (i.Content.ToString().Trim() == SelectedCat.Sex.Trim())
{
this.cmb_sex.SelectedItem = i;
}
}
this.txt_age.Text = SelectedCat.Age.ToString();
foreach (Kind k in list)
{
if (k.KindCd == SelectedCat.Kind)
{
this.cmb_kind.SelectedItem = k;
break;
}
}
this.txt_favorite.Text = SelectedCat.Favorite;
}
}
}
</code></pre>
<h3 id="更新処理の追加"><a href="#%E6%9B%B4%E6%96%B0%E5%87%A6%E7%90%86%E3%81%AE%E8%BF%BD%E5%8A%A0">更新処理の追加</a></h3>
<p>更新ボタンクリックイベントを追加します。<br />
SubWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 更新ボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_mod_Click(object sender, RoutedEventArgs e)
{
this.IsCancel = false;
// データを更新する
using (var context = new PgDbContext())
{
// 対象のテーブルオブジェクトを取得
var table = context.Cats;
// テーブルから対象のデータを取得
var target = table.Single(x => x.No == SelectedCat.No);
// データ変更
target.Name = this.txt_name.Text;
target.Sex = (this.cmb_sex.SelectedItem as ComboBoxItem).Content.ToString();
target.Age = int.Parse(this.txt_age.Text);
target.Kind = (this.cmb_kind.SelectedItem as Kind).KindCd;
target.Favorite = this.txt_favorite.Text;
// DBの変更を確定
context.SaveChanges();
MessageBox.Show("データを更新しました。");
}
this.Close();
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal2000.jpg" alt="検索後の画面" /></p>
<p>対象を選択して「更新」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal2001.jpg" alt="別ウィンドウの表示" /></p>
<p>別ウィンドウが表示され、選択されたデータが各項目に反映されています。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal2002.jpg" alt="内容の変更" /></p>
<p>データを修正し、「更新」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal2003.jpg" alt="確認メッセージの表示" /></p>
<p>確認メッセージが表示されます。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal2004.jpg" alt="データの再検索" /></p>
<p>データが再検索され、更新が反映されていることが確認できました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>無事に親画面から子画面へとデータを渡して処理することができました。<br />
引数をオブジェクトの配列なんかにすると複数のパラメータを渡すことも可能ですね</p>
<p>という感じで、今回はここまでです。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15173
2019-06-29T11:47:37+09:00
2019-06-29T11:47:37+09:00
https://crieit.net/posts/WPF-5d16d1497ca78
【WPF】登録画面を作成して別ウィンドウのモーダル表示をやってみた。
<p>今回はデータ追加用のフォームを別Windowで作成し、追加ボタンがクリックされた際にモーダル表示しようと思います。</p>
<p>プログラムは前回のものを利用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/13/post-2002/" target="_blank" rel="noopener" data-blogcard="1">【WPF】画面のタイトルバーに自作アイコンを表示する</a></p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="新規画面の追加"><a href="#%E6%96%B0%E8%A6%8F%E7%94%BB%E9%9D%A2%E3%81%AE%E8%BF%BD%E5%8A%A0">新規画面の追加</a></h3>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0000.jpg" alt="新規画面の追加" /></p>
<p>ソリューションエクスプローラーでプロジェクトを右クリックし、「追加」>「ウィンドウ」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0001.jpg" alt="クラスの選択" /></p>
<p>新しい項目の追加画面で「ウィンドウ(WPF)」を選択、名前に「SubWindow.xaml」と入力して「追加」ボタンをクリックします。</p>
<h3 id="画面の作成"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BD%9C%E6%88%90">画面の作成</a></h3>
<p>SubWindow.xaml</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.SubWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="追加" Height="300" Width="300"
GlowBrush="{DynamicResource AccentColorBrush}"
Icon="/WpfApp1;component/Resource/Cat.ico"
BorderThickness="1"
WindowStartupLocation="CenterOwner"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}" RenderTransformOrigin="0.522,0.893"/>
<TextBox x:Name="txt_name" Margin="61,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Style="{StaticResource MetroTextBox}"/>
<Label Content="性別:" Margin="10,54,0,0" Style="{StaticResource lb-normal}"/>
<ComboBox x:Name="cmb_sex" HorizontalAlignment="Left" Margin="61,54,0,0" VerticalAlignment="Top" Width="50">
<ComboBoxItem Content="♂" HorizontalAlignment="Left" Width="50"/>
<ComboBoxItem Content="♀" HorizontalAlignment="Left" Width="50"/>
</ComboBox>
<ComboBox x:Name="cmb_kind" HorizontalAlignment="Left" Margin="61,140,0,0" VerticalAlignment="Top" Width="150"/>
<Label Content="年齢:" Margin="10,98,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="txt_age" Margin="61,98,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="10,143,0,0" Style="{StaticResource lb-normal}"/>
<Label Content="好物:" Margin="10,186,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="txt_favorite" Margin="61,186,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Style="{StaticResource MetroTextBox}"/>
<Button x:Name="btn_cansel" Content="キャンセル" HorizontalAlignment="Left" Margin="125,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_cansel_Click"/>
<Button x:Name="btn_add" Content="追加" HorizontalAlignment="Left" Margin="205,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_add_Click"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<h3 id="処理の実装"><a href="#%E5%87%A6%E7%90%86%E3%81%AE%E5%AE%9F%E8%A3%85">処理の実装</a></h3>
<p>SubWindow.xaml.cs</p>
<p>入力された情報を元にデータベースへ追加する処理。</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Npgsql;
using MahApps.Metro.Controls;
namespace WpfApp1
{
/// <summary>
/// SubWindow.xaml の相互作用ロジック
/// </summary>
public partial class SubWindow : MetroWindow
{
public Boolean IsCancel { set; get; }
public SubWindow()
{
InitializeComponent();
// データを取得
// 種別マスタを取得してコンボボックスに設定する
using (var context = new PgDbContext())
{
var mstKind = context.Kinds;
IQueryable<Kind> result = from x in mstKind orderby x.KindCd select x;
var list = result.ToList();
// コンボボックスに設定
this.cmb_kind.ItemsSource = list;
this.cmb_kind.DisplayMemberPath = "KindName";
}
}
/// <summary>
/// キャンセルボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_cansel_Click(object sender, RoutedEventArgs e)
{
this.IsCancel = true;
this.Close();
}
/// <summary>
/// 追加ボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_add_Click(object sender, RoutedEventArgs e)
{
this.IsCancel = false;
// データを追加する
using (var context = new PgDbContext())
{
var cats = context.Cats;
int no = cats.Count();
// データ作成
Cat cat = new Cat();
cat.No = no + 1;
cat.Name = this.txt_name.Text;
cat.Sex = (this.cmb_sex.SelectedItem as ComboBoxItem).Content.ToString();
cat.Age = int.Parse(this.txt_age.Text);
cat.Kind = (this.cmb_kind.SelectedItem as Kind).KindCd;
cat.Favorite = this.txt_favorite.Text;
// データ追加
context.Cats.Add(cat);
// DBの変更を確定
context.SaveChanges();
MessageBox.Show("データを追加しました。");
}
this.Close();
}
}
}
</code></pre>
<h3 id="メイン画面の修正"><a href="#%E3%83%A1%E3%82%A4%E3%83%B3%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">メイン画面の修正</a></h3>
<p>MainWindow.xaml.cs</p>
<p>追加ボタンをクリックした際の処理を修正します。</p>
<pre><code> /// <summary>
/// 追加ボタンクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void add_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("追加ボタンクリック");
var win = new SubWindow();
win.Owner = GetWindow(this);
win.ShowDialog();
if (!win.IsCancel) {
// データ再検索
searchData();
}
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0002.jpg" alt="検索後の画面" /></p>
<p>検索ボタンをクリックしてデータを表示、追加ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0004.jpg" alt="子画面" /></p>
<p>表示された子ウィンドウの各項目を入力、選択し「追加」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0005.jpg" alt="追加完了" /></p>
<p>追加完了メッセージが表示されます。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfModal0006.jpg" alt="データ再検索" /></p>
<p>無事にデータが登録されました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>昔からモーダル画面で何かを操作させるというのはよくありますよね。</p>
<p>操作性なんかを考えると、果たしてそれでいいのかという気持ちもありますが、ひとまずやってみました。</p>
<p>登録フォーム以外でも活用できる場面はあるかと思いますし。</p>
<p>次回は子画面にデータを受け渡してみたいと思います。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15172
2019-06-28T11:48:01+09:00
2019-06-28T11:48:01+09:00
https://crieit.net/posts/WPF-5d157fe1294ab
【WPF】画面のタイトルバーに自作アイコンを表示する
<p>今回は、画面のタイトルバーにアイコンを表示したいと思います。<br />
アイコン自体は無料のサービス「Canva」でちゃちゃっと作ってみました。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/05/31/post-1089/" target="_blank" rel="noopener" data-blogcard="1">無料で使えるデザインツール「Canva」でブログタイトル画像を作る</a></p>
<h2 id="アイコンを作成する"><a href="#%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">アイコンを作成する</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://www.canva.com/" target="_blank" rel="noopener">https://www.canva.com/</a></p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon000.jpg" alt="Canvaでアイコン作り" /></p>
<p>Canva で 猫のシルエットのイラストを適当に追加します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon001.jpg" alt="ダウンロード" /></p>
<p>ダウンロードボタンをクリックしてダウンロードします。</p>
<h3 id="透過させる"><a href="#%E9%80%8F%E9%81%8E%E3%81%95%E3%81%9B%E3%82%8B">透過させる</a></h3>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon002.jpg" alt="Gimp" /></p>
<p>Gimpというツールを使って作成した画像の背景を透過させます。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon003.jpg" alt="ファジー選択ツール" /></p>
<p>先ほど作成した画像をドラッグアンドドロップで表示したら、<br />
ツールから「ファジー選択ツール」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon004.jpg" alt="透過処理" /></p>
<p>背景色(白い)部分をクリックすると、同じ色の箇所が選択状態となります。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon005.jpg" alt="背景色を削除" /></p>
<p>背景色が選択された状態で、「Delete」キーを押下すると選択された部分が透過されます。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon006.jpg" alt="保存" /></p>
<p>ファイルメニューから「名前を付けてエクスポート」を選択して画像を保存します。</p>
<h2 id="画像をアイコンファイルに変換"><a href="#%E7%94%BB%E5%83%8F%E3%82%92%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E5%A4%89%E6%8F%9B">画像をアイコンファイルに変換</a></h2>
<p>こちらもフリーで出来るサービスを利用して「PNG」→「ICO」ファイルに変換します。</p>
<p><a target="_blank" rel="nofollow noopener" href="http://app.tree-web.net/icon_converter/" target="_blank" rel="noopener">アイコンコンバーター</a></p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon008.jpg" alt="アイコンコンバーター" /></p>
<p>ページを表示したら、「ファイルを選択」ボタンをクリックして<br />
先ほど作成した画像ファイルをアップロードします。<br />
<img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon009.jpg" alt="ダウンロード" /></p>
<p>色々なサイズに変換してくれるので、32 x 32 の大きさをダウンロードします。</p>
<h2 id="アイコンをリソースに追加"><a href="#%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%82%92%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AB%E8%BF%BD%E5%8A%A0">アイコンをリソースに追加</a></h2>
<p>ソリューションエクスプローラで、<br />
プロジェクトを右クリックし「追加」>「フォルダ」を選択、「Resource」フォルダを作成します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon010.jpg" alt="リソースの追加" /></p>
<p>作成した「Resource」に作成した「ICO」ファイルをコピー&ペースト等で追加します。</p>
<h2 id="画面を修正する"><a href="#%E7%94%BB%E9%9D%A2%E3%82%92%E4%BF%AE%E6%AD%A3%E3%81%99%E3%82%8B">画面を修正する</a></h2>
<p>Windowのオプションを追加します。<br />
(リソースのパスは次のようにします。)</p>
<pre><code>/プロジェクト名;component/Resource/アイコン名.ico
</code></pre>
<h3 id="通常版"><a href="#%E9%80%9A%E5%B8%B8%E7%89%88">通常版</a></h3>
<pre><code>Icon="/WpfApp1;component/Resource/Cat.ico"
</code></pre>
<h3 id="サイズ変更版"><a href="#%E3%82%B5%E3%82%A4%E3%82%BA%E5%A4%89%E6%9B%B4%E7%89%88">サイズ変更版</a></h3>
<p>こちらは Window のオプションではなく、別途追加してサイズを変更する方法です。<br />
(メトロウィンドウ)</p>
<pre><code> <Controls:MetroWindow.IconTemplate>
<DataTemplate>
<Image Source="/WpfApp1;component/Resource/Cat.ico" Width="22" Height="22" />
</DataTemplate>
</Controls:MetroWindow.IconTemplate>
</code></pre>
<p> </p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfIcon011.jpg" alt="変更後画面" /></p>
<p>アイコンを表示した画面です。<br />
ちょっと小さすぎましたが、アイコン作成時にちゃんとしたサイズを意識すれば問題ありませんね。</p>
<p>今回はここまで。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15171
2019-06-27T09:53:39+09:00
2019-06-27T09:53:39+09:00
https://crieit.net/posts/WPF-5d141393f1862
【WPF】データグリッドにチェックボックス列を設けてワンクリックでチェックできるようにする
<p>今回は、Datagrid にチェックボックス列を追加し、選択したデータを削除できるようにしたいと思います。</p>
<p>デフォルトで、「DataGridCheckBoxColumn」というのがあるのですが、これだと行を選択したあとにチェックしなければならず、なんか操作性が悪いため別の方法で実装します。</p>
<p>プログラムは、前回のプログラムを流用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/09/post-1956/" target="_blank" rel="noopener" data-blogcard="1">【WPF】PostgreSQL に接続してデータを操作(登録、更新、削除)してみる</a></p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<p>データグリッド列の先頭に次の「DataGridTemplateCoumn」を追加します。</p>
<p>MainWindow.xaml</p>
<pre><code><DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</code></pre>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="クラス追加"><a href="#%E3%82%AF%E3%83%A9%E3%82%B9%E8%BF%BD%E5%8A%A0">クラス追加</a></h3>
<p>チェックボックスにバインドする列を追加したクラスを作成します。</p>
<p>CatModel.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp1
{
public class CatModel
{
public CatModel() {
}
public CatModel(int No, String Name, String Sex, int Age, String Kind, String Favorite) {
this.IsChecked = false;
this.No = No;
this.Name = Name;
this.Sex = Sex;
this.Age = Age;
this.Kind = Kind;
this.Favorite = Favorite;
}
public Boolean IsChecked { get; set; }
public int No { get; set; }
public String Name { get; set; }
public String Sex { get; set; }
public int Age { get; set; }
public String Kind { get; set; }
public String Favorite { get; set; }
}
}
</code></pre>
<h3 id="データ取得処理の修正"><a href="#%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%96%E5%BE%97%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">データ取得処理の修正</a></h3>
<p>取得したデータを作成したクラスにマッピングします。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> List<CatModel> resultList = new List<CatModel>();
foreach (Cat cat in result.ToList())
{
resultList.Add(new CatModel(cat.No, cat.Name, cat.Sex, cat.Age, cat.Kind, cat.Favorite));
}
e.Result = resultList;
</code></pre>
<h3 id="データグリッドに設定する処理の修正"><a href="#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B0%E3%83%AA%E3%83%83%E3%83%89%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">データグリッドに設定する処理の修正</a></h3>
<p>データグリッドに設定するリストのクラスを変更します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 検索完了処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcessCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.dataGrid.ItemsSource = e.Result as List<CatModel>;
ToggleProgressRing();
}
</code></pre>
<h3 id="削除処理の修正"><a href="#%E5%89%8A%E9%99%A4%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">削除処理の修正</a></h3>
<p>削除ボタンがクリックされたら、<br />
チェックボックスが選択されているデータを削除するように修正します。</p>
<pre><code> /// <summary>
/// 削除ボタンクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void del_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("削除ボタンクリック");
// データを削除する
using (var context = new PgDbContext())
{
int checkCount = 0;
List<CatModel> list = this.dataGrid.ItemsSource as List<CatModel>;
foreach (CatModel cat in list)
{
if (cat.IsChecked)
{
checkCount++;
// 対象のテーブルオブジェクトを取得
var table = context.Cats;
// テーブルから対象のデータを取得
var target = table.Single(x => x.No == cat.No);
// データ削除
table.Remove(target);
// DBの変更を確定
context.SaveChanges();
}
}
if (checkCount == 0)
{
MessageBox.Show("削除対象にチェックがされていません。");
return;
}
}
// データ再検索
searchData();
MessageBox.Show("データを削除しました。");
}
</code></pre>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfDatagridCheckbox000.jpg" alt="チェックボックス追加" /></p>
<p>追加したチェックボックスをいくつかチェックして削除ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfDatagridCheckbox001.jpg" alt="データ削除完了" /></p>
<p>無事にデータが削除されました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>データグリッドにチェックボックスをつけるって結構よくある要件ですよね。<br />
デフォルトでこうしてくれればいいんですけど。</p>
<p>まあとりあえずはこんな感じでいいんじゃないでしょうか。</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15168
2019-06-26T09:51:09+09:00
2019-06-26T09:51:09+09:00
https://crieit.net/posts/WPF-PostgreSQL-5d12c17d61f60
【WPF】PostgreSQL に接続してデータを操作(登録、更新、削除)してみる
<p>おはようございます。</p>
<p>前回に引き続き PostgreSQL を使って、登録、更新、削除をしてみたいと思います。</p>
<p>前回の記事はこちら。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/08/08/post-1948/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】PostgreSQL に接続してデータを取得して表示する</a></p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="追加処理の修正"><a href="#%E8%BF%BD%E5%8A%A0%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">追加処理の修正</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 追加ボタンクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void add_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("追加ボタンクリック");
// データを追加する
// PgDbContext に変更
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var context = new PgDbContext())
{
// データ作成
// テーブルはコンテキスト経由でアクセスする
//var table = context.GetTable<Cat>();
Cat cat = new Cat();
cat.No = 5;
cat.No = 5;
cat.Name = "こなつ";
cat.Sex = "♀";
cat.Age = 7;
cat.Kind = "01";
cat.Favorite = "布団";
// データ追加
// コンテキスト経由でエンティティを追加
//table.InsertOnSubmit(cat);
context.Cats.Add(cat);
// DBの変更を確定
// メソッド変更
//context.SubmitChanges();
context.SaveChanges();
}
// データ再検索
searchData();
MessageBox.Show("データを追加しました。");
}
</code></pre>
<h3 id="更新処理"><a href="#%E6%9B%B4%E6%96%B0%E5%87%A6%E7%90%86">更新処理</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 更新ボタンクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void upd_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("更新ボタンクリック");
// 選択チェック
if (this.dataGrid.SelectedItem == null)
{
MessageBox.Show("更新対象を選択してください。");
return;
}
// データを更新する
// PgDbContext に変更
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var context = new PgDbContext())
{
// 対象のテーブルオブジェクトを取得
// テーブルはコンテキスト経由でアクセスする
//var table = context.GetTable<Cat>();
var table = context.Cats;
// 選択されているデータを取得
Cat cat = this.dataGrid.SelectedItem as Cat;
// テーブルから対象のデータを取得
var target = table.Single(x => x.No == cat.No);
// データ変更
target.Favorite = "高いところ";
// DBの変更を確定
// メソッド変更
//context.SubmitChanges();
context.SaveChanges();
}
// データ再検索
searchData();
MessageBox.Show("データを更新しました。");
}
</code></pre>
<p> </p>
<h3 id="削除処理"><a href="#%E5%89%8A%E9%99%A4%E5%87%A6%E7%90%86">削除処理</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 削除ボタンクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void del_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("追加ボタンクリック");
// 選択チェック
if (this.dataGrid.SelectedItem == null)
{
MessageBox.Show("削除対象を選択してください。");
return;
}
// データを削除する
// PgDbContext に変更
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var context = new PgDbContext())
{
// 対象のテーブルオブジェクトを取得
// テーブルはコンテキスト経由でアクセスする
//var table = context.GetTable<Cat>();
var table = context.Cats;
// 選択されているデータを取得
Cat cat = this.dataGrid.SelectedItem as Cat;
// テーブルから対象のデータを取得
var target = table.Single(x => x.No == cat.No);
// データ削除
// メソッド変更
//table.DeleteOnSubmit(target);
table.Remove(target);
// DBの変更を確定
context.SaveChanges();
}
// データ再検索
searchData();
MessageBox.Show("データを削除しました。");
}
</code></pre>
<p> </p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>サクッとした記事になりましたが、ひとまず PostgreSQL はここまでとして次回は Oracle を試してみたいと思います。</p>
<p>ソースはこちら</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/doraxdora/SampleWpfPostgreSQL1" target="_blank" rel="noopener noreferrer">GitHub</a></p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15166
2019-06-25T10:05:02+09:00
2019-06-25T10:05:02+09:00
https://crieit.net/posts/WPF-PostgreSQL
【WPF】PostgreSQL に接続してデータを取得して表示する
<p>おはようございます。</p>
<p>今回は、PostgreSQLを使ってデータを検索、データグリッドに表示してみます。<br />
お決まりですが、プログラムは前回までのものを流用します。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/07/28/post-1873/" target="_blank" rel="noopener" data-blogcard="1">【WPF】ProgressRingを使って時間のかかる処理を分かりやすくする</a></p>
<p>また、PostgreSQLをインストールしていない場合は次の記事を参照して、パソコンにインストールしてください。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/07/25/post-1748/" target="_blank" rel="noopener" data-blogcard="1">PostgreSQL 9.6.3 をインストールしてテーブルを作成する</a></p>
<h2 id="Nuget でパッケージをダウンロード"><a href="#Nuget+%E3%81%A7%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89">Nuget でパッケージをダウンロード</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfPostgreSQL000.jpg" alt="NuGetパッケージ管理を開く" /></p>
<p>ソリューションエクスプローラーからプロジェクトを選択、右クリックし<br />
「Nuget パッケージの管理」を選択</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfPostgreSQL001.jpg" alt="NuGetパッケージ管理" /></p>
<p>Nuget パッケージ管理画面が表示されるので、<br />
検索窓に「Npgsql 6」を入力し、「EntityFramework6.Npgsql」を選択、<br />
インストールボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfPostgreSQL002.jpg" alt="プレビュー画面" /></p>
<p>プレビュー画面が表示される場合は「OK」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfPostgreSQL003.jpg" alt="出力ビュー" /></p>
<p>出力ビューに「終了」が表示されれば完了です。</p>
<h2 id="スキーマの作成"><a href="#%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E3%81%AE%E4%BD%9C%E6%88%90">スキーマの作成</a></h2>
<p>PostgreSQL ではスキーマ単位の管理をしておかないと困ることになります。</p>
<p>スキーマ指定しないでテーブル作成すると「public」スキーマに作成されるのですが、<br />
C#からの接続時には必ず(やってみた限りでは)スキーマ指定しないといけないので、まずはスキーマを作成しておきます。</p>
<pre><code>CREATE SCHEMA dora;
</code></pre>
<h2 id="テーブルの作成"><a href="#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90">テーブルの作成</a></h2>
<p>作成したスキーマににテーブルを作成<br />
SQLite の時と同じテーブル、データを用意します。</p>
<p>このとき、テーブル名やカラム名は小文字にしておくこと。</p>
<pre><code>CREATE TABLE IF NOT EXISTS dora.mstkind (
kind_cd CHAR(2) NOT NULL
, kind_name VARCHAR(20)
, primary key (kind_cd)
);
CREATE TABLE IF NOT EXISTS dora.tblcat (
no INTEGER NOT NULL
, name VARCHAR(20) NOT NULL
, sex CHAR(3) NOT NULL
, age INTEGER DEFAULT 0 NOT NULL
, kind_cd CHAR(2) DEFAULT '00' NOT NULL
, favorite VARCHAR(40)
, PRIMARY KEY (no)
);
INSERT INTO DORA.MSTKIND VALUES ('01', 'キジトラ');
INSERT INTO DORA.MSTKIND VALUES ('02', '長毛種(不明)');
INSERT INTO DORA.MSTKIND VALUES ('03', 'ミケ(っぽい)');
INSERT INTO DORA.MSTKIND VALUES ('04', 'サビ');
INSERT INTO DORA.MSTKIND VALUES ('09', 'その他');
INSERT INTO DORA.TBLCAT VALUES('1','そら','♂','6','01','犬の人形');
INSERT INTO DORA.TBLCAT VALUES('2','りく','♂','5','02','人間');
INSERT INTO DORA.TBLCAT VALUES('3','うみ','♀','4','03','高級ウェットフード');
INSERT INTO DORA.TBLCAT VALUES('4','こうめ','♀','2','04','横取りフード');
</code></pre>
<h2 id="設定ファイルの修正"><a href="#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BF%AE%E6%AD%A3">設定ファイルの修正</a></h2>
<p>次のようにします。<br />
重要な部分は、「entityFramework」タグと「system.data」タグ。</p>
<p>App.config</p>
<pre><code><?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v13.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Npgsql" />
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql" type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories>
</system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Npgsql" publicKeyToken="5d8b90d52f46fda7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.2.5.0" newVersion="3.2.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
</code></pre>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="新規クラスの追加"><a href="#%E6%96%B0%E8%A6%8F%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E8%BF%BD%E5%8A%A0">新規クラスの追加</a></h3>
<p>DbContextを継承したクラスを作成します。<br />
このクラスでデータベースへの接続、Entityへのマッピングなどを行います。<br />
デフォルトのスキーマを変更する場合、「OnModelCreating」メソッドにて設定可能です。</p>
<p>PgDbContext.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using Npgsql;
namespace WpfApp1
{
class PgDbContext : DbContext
{
private const string ConnectionString = "Server=localhost;User ID=USER01;Password=USER01;Database=DB01;port=5432";
// コンストラクタにて接続文字列を設定
public PgDbContext() : base(new NpgsqlConnection(ConnectionString), true) { }
public DbSet<Kind> Kinds { get; set; }
public DbSet<Cat> Cats { get; set; }
// スキーマを変更する場合にはここに設定
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Configure default schema
modelBuilder.HasDefaultSchema("dora");
}
}
}
</code></pre>
<h3 id="Entityクラスの修正"><a href="#Entity%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E4%BF%AE%E6%AD%A3">Entityクラスの修正</a></h3>
<p>アノテーションが今までのとちょっと違うので修正します。</p>
<p>Kind.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WpfApp1
{
[Table("mstkind")]
class Kind
{
[Key]
[Column("kind_cd")]
public String KindCd { get; set; }
[Column("kind_name")]
public String KindName { get; set; }
}
}
</code></pre>
<p>Cat.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WpfApp1
{
[Table("tblcat")]
class Cat
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Column("no")]
public int No { get; set; }
[Column("name")]
public String Name { get; set; }
[Column("sex")]
public String Sex { get; set; }
[Column("age")]
public int Age { get; set; }
[Column("kind_cd")]
public String Kind { get; set; }
[Column("favorite")]
public String Favorite { get; set; }
}
}
</code></pre>
<h3 id="宣言の追加"><a href="#%E5%AE%A3%E8%A8%80%E3%81%AE%E8%BF%BD%E5%8A%A0">宣言の追加</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code>using Npgsql;
using System.ComponentModel;
</code></pre>
<h3 id="接続処理の変更"><a href="#%E6%8E%A5%E7%B6%9A%E5%87%A6%E7%90%86%E3%81%AE%E5%A4%89%E6%9B%B4">接続処理の変更</a></h3>
<p>テーブル作成以外、全ての箇所を変更します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code>//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var context = new PgDbContext())
</code></pre>
<p>テーブル作成は今まで通りコマンドで行います。<br />
(また別途、DbContext でのやり方は紹介します)</p>
<h3 id="テーブル作成クエリの変更"><a href="#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E4%BD%9C%E6%88%90%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%AE%E5%A4%89%E6%9B%B4">テーブル作成クエリの変更</a></h3>
<p>SQLite とは微妙に違うところ(型、長さ)を変更。</p>
<p>MainWindow.xaml.cs</p>
<pre><code>// テーブルが存在しなければ作成する
// 種別マスタ
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE IF NOT EXISTS mstkind (");
sb.Append(" kind_cd CHAR(2) NOT NULL");
sb.Append(" , kind_name VARCHAR(20)");
sb.Append(" , PRIMARY KEY (kind_cd)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
// 猫テーブル
sb.Clear();
sb.Append("CREATE TABLE IF NOT EXISTS tblcat (");
sb.Append(" no INTEGER NOT NULL");
sb.Append(" , name VARCHAR(20) NOT NULL");
sb.Append(" , sex CHAR(3) NOT NULL");
sb.Append(" , age INTEGER DEFAULT 0 NOT NULL");
sb.Append(" , kind_cd CHAR(2) DEFAULT '00' NOT NULL");
sb.Append(" , favorite VARCHAR(40)");
sb.Append(" , PRIMARY KEY (no)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
</code></pre>
<h3 id="検索処理の修正"><a href="#%E6%A4%9C%E7%B4%A2%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">検索処理の修正</a></h3>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 検索処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcess(object sender, DoWorkEventArgs e)
{
// 猫データマスタを取得してコンボボックスに設定する
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
// PgDbContext に変更
using (var context = new PgDbContext())
{
String searchName = this.search_name.Text;
String searchKind = (this.search_kind.SelectedValue as Kind).KindCd;
// データを取得
// context から DbSet を取得
//Table<Cat> tblCat = con.GetTable<Cat>();
var tblCat = context.Cats;
// サンプルなので適当に組み立てる
IQueryable<Cat> result;
if (searchKind == "")
{
// 名前は前方一致のため常に条件していしても問題なし
result = from x in tblCat
where x.Name.StartsWith(searchName)
orderby x.No
select x;
}
else
{
result = from x in tblCat
where x.Name.StartsWith(searchName) & x.Kind == searchKind
orderby x.No
select x;
}
this.dataGrid.ItemsSource = result.ToList();
}
}
</code></pre>
<h3 id="コンバーターの修正"><a href="#%E3%82%B3%E3%83%B3%E3%83%90%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AE%E4%BF%AE%E6%AD%A3">コンバーターの修正</a></h3>
<p>データグリッドに表示する際に値を変換している箇所も、DB接続しているため変更します。</p>
<p>KindConverter.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Linq;
using System.Data.SQLite;
using System.Data.SQLite.Linq;
// Converter 用
// IValueConverter、CultureInfo
using System.Windows.Data;
using System.Globalization;
namespace WpfApp1
{
/// <summary>
/// 種別コンバータークラス.
/// </summary>
public class KindConverter : IValueConverter
{
/// <summary>
/// データ変換処理
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
// PgDbContext に変更
using (var context = new PgDbContext())
{
// データを取得
//Table<Kind> tblCat = con.GetTable<Kind>();
//Kind k = tblCat.Single(c => c.KindCd == value as String);
var kind = context.Kinds.SingleOrDefault(c => c.KindCd == (String)value);
if (kind != null)
{
return kind.KindName;
}
return "";
}
}
/// <summary>
/// データ復元処理
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
using (var context = new PgDbContext())
{
// データを取得
//Table<Kind> tblCat = con.GetTable<Kind>();
//Kind k = tblCat.Single(c => c.KindCd == value as String);
var kind = context.Kinds.SingleOrDefault(c => c.KindName == value as String);
if (kind != null)
{
return kind.KindCd;
}
}
return "";
}
}
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/08/WpfPostgreSQL004.jpg" alt="検索結果" /></p>
<p>無事に起動、検索することができました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>ひとまず、元々の処理(SQLite、MySQL)とあまり変更せずに実装することができました。</p>
<p>ちょっと長くなってしまったので、<br />
登録、更新、削除はまた次回とさせていただきます。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15159
2019-06-24T10:48:16+09:00
2019-06-24T10:48:16+09:00
https://crieit.net/posts/WPF-ProgressRing
【WPF】ProgressRingを使って時間のかかる処理を分かりやすくする
<p>WEBなんかでよく見かける、処理中にローディング画像を表示するってのをやってみます。</p>
<p>重い処理なんかで、ローディング表示がない場合はユーザーが動いているのかどうか心配になり、挙句の果てに強制終了してしまったりしますので、大事ですよね。<br />
体感速度も違ってきますし。</p>
<p>プログラムは前回のものを利用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/07/27/post-1871/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】MahApps.Metro で見た目をスタイリッシュにしてみる </a></p>
<h2 id="スタイルの追加"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E8%BF%BD%E5%8A%A0">スタイルの追加</a></h2>
<p>StyleDic.xaml</p>
<p>宣言の追加</p>
<pre><code><ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:WpfApp1.Style">
</code></pre>
<p>スタイルの追加</p>
<pre><code> <!-- プログレスリング -->
<Style x:Key="pgr-normal" TargetType="{x:Type Mah:ProgressRing}" >
<Setter Property="Foreground" Value="#33adff" />
<Setter Property="IsActive" Value="False" />
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="Panel.ZIndex" Value="100" />
</Style>
<!-- プログレスオーバーレイ-->
<Style x:Key="rec-overlay" TargetType="{x:Type Rectangle}" >
<Setter Property="Fill" Value="#000000" />
<Setter Property="Opacity" Value="0.2" />
<Setter Property="Panel.ZIndex" Value="1000" />
<Setter Property="Margin" Value="0,0,0,30" />
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</code></pre>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<p>MainWindow.xaml</p>
<p>抜粋</p>
<pre><code><!-- Gridの高さと幅を設定 -->
<Grid Height="350" Width="530">
<!-- プログレスリングとオーバーレイを追加 -->
<Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />
<Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>
</code></pre>
<p> </p>
<p>全体</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.MainWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="一覧" Height="350" Width="530"
GlowBrush="{DynamicResource AccentColorBrush}"
BorderThickness="1"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid Height="350" Width="530">
<Grid.Resources>
<local:KindConverter x:Key="KindConv"/>
</Grid.Resources>
<Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />
<Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="search_name" Margin="56,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>
<ComboBox x:Name="search_kind" Margin="252,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125" Style="{StaticResource MetroComboBox}"/>
<Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75" Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>
<DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="50"/>
<DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="True" Width="100"/>
<DataGridTextColumn Binding="{Binding Sex}" ClipboardContentBinding="{x:Null}" Header="性別" IsReadOnly="True" Width="40"/>
<DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="True" Width="40"/>
<DataGridTextColumn Binding="{Binding Kind, Converter={StaticResource KindConv<span>}</span><span>}</span>" ClipboardContentBinding="{x:Null}" Header="種別" IsReadOnly="True" Width="120"/>
<DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="True" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<p> </p>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="ライブラリ使用宣言の追加"><a href="#%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E4%BD%BF%E7%94%A8%E5%AE%A3%E8%A8%80%E3%81%AE%E8%BF%BD%E5%8A%A0">ライブラリ使用宣言の追加</a></h3>
<p>MainWindow.xaml.cs</p>
<p>抜粋</p>
<pre><code>using System.ComponentModel;
</code></pre>
<p> </p>
<h3 id="検索処理の修正"><a href="#%E6%A4%9C%E7%B4%A2%E5%87%A6%E7%90%86%E3%81%AE%E4%BF%AE%E6%AD%A3">検索処理の修正</a></h3>
<p>検索処理を、BackgroundWorkerを使って非同期処理として分離します。</p>
<p>MainWindow.xaml.cs</p>
<pre><code> /// <summary>
/// 検索処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcess(object sender, DoWorkEventArgs e)
{
// 時間のかかるようにする
System.Threading.Thread.Sleep(3000);
using (var conn = new MySqlConnection("Database=DB01;Data Source=localhost;User Id=USER01;Password=USER01; sqlservermode=True;"))
{
conn.Open();
// 猫データマスタを取得してコンボボックスに設定する
using (DataContext con = new DataContext(conn))
{
String searchName = (e.Argument as Object[])[0] as String;
String searchKind = (e.Argument as Object[])[1] as String;
// データを取得
Table<Cat> tblCat = con.GetTable<Cat>();
// サンプルなので適当に組み立てる
IQueryable<Cat> result;
if (searchKind == "")
{
// 名前は前方一致のため常に条件していしても問題なし
result = from x in tblCat
where x.Name.StartsWith(searchName)
orderby x.No
select x;
}
else
{
result = from x in tblCat
where x.Name.StartsWith(searchName) & x.Kind == searchKind
orderby x.No
select x;
}
e.Result = result.ToList();
}
conn.Close();
}
}
/// <summary>
/// 検索完了処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcessCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.dataGrid.ItemsSource = e.Result as List<Cat>;
ToggleProgressRing();
}
/// <summary>
/// 処理中イメージの表示/非表示切り替え
///
/// </summary>
private void ToggleProgressRing()
{
if (this.loading_image.IsActive)
{
this.loading_image.IsActive = false;
this.rec_overlay.Visibility = Visibility.Collapsed;
}
else
{
this.loading_image.IsActive = true;
this.rec_overlay.Visibility = Visibility.Visible;
}
}
</code></pre>
<h3 id="メソッドの修正"><a href="#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E4%BF%AE%E6%AD%A3">メソッドの修正</a></h3>
<p>検索ボタンをクリックした際に、先ほど追加した非同期処理を呼び出すように修正します。</p>
<pre><code> /// <summary>
/// 検索ボタンクリックイベント.
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void search_button_Click(object sender, RoutedEventArgs e)
{
logger.Info("検索ボタンクリック");
Object[] param = new Object[2];
param[0] = this.search_name.Text;
param[1] = (this.search_kind.SelectedValue as Kind).KindCd;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += SearchProcess;
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SearchProcessCompleted);
worker.RunWorkerAsync(param);
ToggleProgressRing();
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p>動画<br />
<a target="_blank" rel="nofollow noopener" href="https://www.youtube.com/embed/MOaQGtqEoUA">https://www.youtube.com/embed/MOaQGtqEoUA</a></p>
<p>いい感じですね。</p>
<p>ローディング表示だけだと、処理中にボタンなんかが押せてしまうので図形をかぶせるようにしてみました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>簡単な(画面の少ない)アプリであればこんな方法でも十分かなと思います。</p>
<p>ソースはこちら</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/doraxdora/SampleWpfMySQL3" target="_blank" rel="noopener noreferrer">GitHub</a></p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15147
2019-06-22T11:28:45+09:00
2019-06-22T11:28:45+09:00
https://crieit.net/posts/WPF-MahApps-Metro
【WPF】MahApps.Metro で見た目をスタイリッシュにしてみる
<p>今ではスマートフォンやタブレットをほとんどの人が使っていることもあり<br />
見た目や操作性が重視される世の中になりましたよね。</p>
<p>WPFはスタイルなんかも結構簡単に弄れるし、<br />
自力でかっこよくすることもできるんだと思いますが、<br />
今回は簡単にスタイリッシュに変更できるパッケージを紹介します。</p>
<p>プログラムは前回のものを利用します。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/07/24/post-1729/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】MySQL(MariaDB)に接続してデータを DataGrid に表示してみる</a></p>
<h2 id="MahApps.Metro"><a href="#MahApps.Metro">MahApps.Metro</a></h2>
<blockquote>公式から紹介文を訳して転載
Mahapps.Metroは、デフォルトのコントロールのスタイルをオーバーライドし、それらにメトロアッシュの外観を与えます。スタイルだけではありません。 MahApps.Metroには、Windows Phoneのコンセプトに基づいたカスタムコントロールもいくつか含まれています。</blockquote>
<p>簡単に言うと、少しの修正で既存のWPFアプリをかっこよく出来まっせってことですね。</p>
<h2 id="NuGetでパッケージをダウンロード"><a href="#NuGet%E3%81%A7%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89">NuGetでパッケージをダウンロード</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro000.jpg"><img class="wp-image-1866 size-full" src="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro000.jpg" alt="NuGetパッケージ管理" /></a></p>
<p>パッケージエクスプローラの「参照」を右クリックし、「NuGetパッケージの管理」を選択します。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro001.jpg" alt="パッケージのインストール" /></p>
<p>MahApps で絞り込みし、「MahApps.Metro」を選択、<br />
「インストール」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro002.jpg" alt="プレビュー画面" /></p>
<p>プレビュー画面が表示された場合は「OK」ボタンをクリックします。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro003.jpg" alt="出力ビュー" /></p>
<p>出力ビューに「終了」が出力されれば完了です。</p>
<h2 id="画面の修正"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BF%AE%E6%AD%A3">画面の修正</a></h2>
<h3 id="XML名前空間の追加"><a href="#XML%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%81%AE%E8%BF%BD%E5%8A%A0">XML名前空間の追加</a></h3>
<p>MainWindow.xaml</p>
<p>抜粋</p>
<pre><code> xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
</code></pre>
<h3 id="Windowの変更"><a href="#Window%E3%81%AE%E5%A4%89%E6%9B%B4">Windowの変更</a></h3>
<pre><code>Window を Mah:MetroWindow に変更
<Mah:MetroWindow x:Class="WpfApp1.MainWindow"
枠線をつける
GlowBrush="Blue"
BorderThickness="0"
</code></pre>
<p>全体</p>
<pre><code><Mah:MetroWindow x:Class="WpfApp1.MainWindow"
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:WpfApp1"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="一覧" Height="350" Width="530"
GlowBrush="Blue"
BorderThickness="0"
>
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid>
<Grid.Resources>
<local:KindConverter x:Key="KindConv"/>
</Grid.Resources>
<Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>
<TextBox x:Name="search_name" Margin="56,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Style="{StaticResource MetroTextBox}"/>
<Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>
<ComboBox x:Name="search_kind" Margin="252,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125" Style="{StaticResource MetroComboBox}"/>
<Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75" Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>
<DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="50"/>
<DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="True" Width="100"/>
<DataGridTextColumn Binding="{Binding Sex}" ClipboardContentBinding="{x:Null}" Header="性別" IsReadOnly="True" Width="40"/>
<DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="True" Width="40"/>
<DataGridTextColumn Binding="{Binding Kind, Converter={StaticResource KindConv<span>}</span><span>}</span>" ClipboardContentBinding="{x:Null}" Header="種別" IsReadOnly="True" Width="120"/>
<DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="True" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
<Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>
</Grid>
</Mah:MetroWindow>
</code></pre>
<h2 id="プログラムの修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E4%BF%AE%E6%AD%A3">プログラムの修正</a></h2>
<h3 id="パッケージ利用宣言"><a href="#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E5%88%A9%E7%94%A8%E5%AE%A3%E8%A8%80">パッケージ利用宣言</a></h3>
<p>MainWindow.xaml.cs</p>
<p>抜粋</p>
<pre><code>using MahApps.Metro.Controls
</code></pre>
<h3 id="クラス変更"><a href="#%E3%82%AF%E3%83%A9%E3%82%B9%E5%A4%89%E6%9B%B4">クラス変更</a></h3>
<p>MainWindow.xaml.cs</p>
<p>抜粋</p>
<pre><code>public partial class MainWindow : MetroWindow
</code></pre>
<h2 id="リソースの追加"><a href="#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E8%BF%BD%E5%8A%A0">リソースの追加</a></h2>
<p>App.xaml</p>
<pre><code><Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/07/MahAppsMetoro004.jpg" alt="変更後の画面" /></p>
<p>簡単に変更できましたね。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>Mahapps は他にも色々と出来るみたいなのでそのうちやってみたいと思います。</p>
<p>ソースはこちら</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/doraxdora/SampleWpfMySQL2" target="_blank" rel="noopener noreferrer">GitHub</a></p>
<p>ではでは。</p>
<p> </p>
doraxdora