WPFでRadioButtonにEnumをBindする
目次
環境
実現したいこと
RadioButtonにViewModelのプロパティ値(Enum)をBindする。
実装の方針
- 各RadioButtonのIsCheckedにEmun値をバインドさせる。
- Converterを用意して、Bool値に変換する。
実装
Converter
検索すると色々な方法があるみたいですが、簡単にこんな感じで作ってみました。
[ValueConversion(typeof(Enum), typeof(bool))] public class RadioButtonConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || parameter == null) return false; return value.ToString() == parameter.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || parameter == null) return Binding.DoNothing; if ((bool)value) { return Enum.Parse(targetType, parameter.ToString()); } return Binding.DoNothing; } }
Bindingしない時は Binding.DoNothing を使うようです。
Binding.DoNothing フィールド (System.Windows.Data)
VMとEnum
public class ViewModel { public TestEnum TestKind { get; set; } = TestEnum.Test4; } public enum TestEnum { Test1, Test2, Test3, Test4 }
View
RadioButtonはGroupNameを付けておく。
ConverterParameterを指定する。
<Window x:Class="WpfRadioButtonSample.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:WpfRadioButtonSample" mc:Ignorable="d" Title="MainWindow" Height="100" Width="100"> <Window.Resources> <local:RadioButtonConverter x:Key="EnumConverter" /> </Window.Resources> <StackPanel> <RadioButton GroupName="Test" Content="Test1" IsChecked="{Binding TestKind, ConverterParameter=Test1, Converter={StaticResource EnumConverter}}"/> <RadioButton GroupName="Test" Content="Test2" IsChecked="{Binding TestKind, ConverterParameter=Test2, Converter={StaticResource EnumConverter}}"/> <RadioButton GroupName="Test" Content="Test3" IsChecked="{Binding TestKind, ConverterParameter=Test3, Converter={StaticResource EnumConverter}}"/> <RadioButton GroupName="Test" Content="Test4" IsChecked="{Binding TestKind, ConverterParameter=Test4, Converter={StaticResource EnumConverter}}"/> </StackPanel> </Window>
ちょっとばかし嵌ってしまったので、メモ。
Firebird .NETProviderで実行計画を取得する
目次
環境
実装
FBCommandクラスにCommandPlanメソッドがあるので、それを呼び出すだけです。
using (var con = new FbConnection("接続文字列")) using (var command = con.CreateCommand()) { con.Open(); command.CommandText = @"select * from rdb$indices where rdb$system_flag = 0"; command.ExecuteReader(); Console.WriteLine(command.CommandPlan); }
このメソッド、Browsable属性がfalseですが、特に問題ないでしょう。
いわゆる、Isqlでいう set plan on; の状態なので、SQLを実行しないと実行計画を取得できません。
実行計画の見方
他のDBMSの実行計画と比べると、Firebirdは少し特徴的に見えますが、そういう時は
Referenceを参照しましょう。
ちゃんとDocumentが用意されてます。
Firebirdでテーブル状態に合わせてINSERTとUPDATEを実行する
実は過去に、こんな記事を書いていました。
ponyoth.hateblo.jp
上記のFirebird版になります。
データ更新の際に、すでに該当行があればUPDATE、なければINSERTする単純な例です。
ただし、Firebirdには「UPDATE OR INSERT」という構文があります。
そのため、「MERGE」と「UPDATE OR INSERT」を並記します。
目次
検証環境
- Firebird 2.5.5
テスト用テーブルの作成
create table MergeTest( Id int unique not null, Memo varchar(200) ); insert into MergeTest values(1, 'test1'); insert into MergeTest values(2, 'test2'); insert into MergeTest values(3, 'test3'); insert into MergeTest values(4, 'test4');
「MERGE」の場合
merge into MergeTest as t using (select 4 Id, 'change' Memo from MergeTest) as s on (t.Id = s.Id) when matched then update set t.Memo = s.Memo when not matched then insert (Id, Memo) values(s.Id, s.Memo); merge into MergeTest as t using (select 5 Id, 'test5' Memo from MergeTest) as s on (t.Id = s.Id) when matched then update set t.Memo = s.Memo when not matched then insert (Id, Memo) values(s.Id, s.Memo);
リファレンスはこちら。
MERGE
「UPDATE OR INSERT」の場合
update or insert into MERGETEST (ID, MEMO) values (4, 'change') matching (ID); update or insert into MERGETEST (ID, MEMO) values (5, 'test5') matching (ID);
リファレンスはこちら。
UPDATE OR INSERT
結果
「MERGE」は他のRDBMSと同じように書けます。
今回の目的の場合は、「UPDATE OR INSERT」の方が分かりやすそうですね。
AvalonEditをTabControlでつかう
自作ツールのTabControlのContentにAvalonEditを導入しようとしたところ、
思いの外苦戦したので記録しておきます。
目次
環境
問題点
- TabControlでTabを切り替えた時に、AvalonEdithへの入力値が引き継がれてしまう
XAMLでTabItemを明示的に記述した場合は再現しない。
ContentTemplateのDataTemplateを使って動的にタブを制御すると再現する。
あぁ、そういうことかって感はありますよね。
- イメージ
解決
わりと無理やりですが、TextプロパティをBindして、書き換えるようにしました。
こんな感じのコントロールを作ってしまいます。
何か見落としている気がしないでもないですけど、意図した事ができるようになったので良し。
ちゃんとした解決法知っている人がいたら教えてください。
AvalonEditを使って、SQL文にSyntaxHighlightつけたい
自作ツールにFirebirdのSQL文を入力した際に、SyntaxHighlightできるようにしたい!
ということで、AvalonEditを使ってみました。
目次
環境
AvalonEditとは
WPFベースのテキストエディターコンポーネントです。
SharpDevelop というOSSのIDEでテキストエディタとして使われているものです。
そのため、SyntaxHighlight のみならずコード補完等も出来るようです。
AvalonEditの詳しい解説は下記のDocumentを参照。
* AvalonEdit - Table of Content
実装
ライブラリの取得
公式ページにあるように nuget から Install 可能です。
Install-Package AvalonEdit
エディタの配置
名前空間設定して、TextEditorを配置すればよし。
<Window x:Class="AvalonEditSample.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:avalon="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:local="clr-namespace:AvalonEditSample" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <avalon:TextEditor /> </Window>
SyntaxHighlight の設定
AvalonEdit では、SyntaxHighlightingプロパティで指定できる言語がいくつかあります。
C#, PowerShell, HTML, CSS, VB, C++, Java ,その他諸々が対応しています。
以下のコードを確認すると、対応状況が分かります。
AvalonEdit/Resources.cs at master · icsharpcode/AvalonEdit · GitHub
AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources at master · icsharpcode/AvalonEdit · GitHub
C#の設定をする場合はこんな感じでOKです。
<avalon:TextEditor SyntaxHighlighting="C#"/>
SyntaxHighlight のカスタマイズ
下記に従って、任意の設定が可能です。
AvalonEdit - Table of Content
適当にFirebirdのキーワードを突っ込んだ xshdファイルを作成します。
<SyntaxDefinition name="SQL" extensions=".sql" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> ... <Color name="Keyword" foreground="#FF0000FF" fontWeight="bold" exampleText="SELECT" /> <Keywords color="Keyword"> ... <Word>INDEX</Word> <Word>INNER</Word> <Word>INPUT_TYPE</Word> <Word>INSENSITIVE</Word> <Word>INSERT</Word> <Word>INSERTING</Word> <Word>INT</Word> <Word>INTEGER</Word> <Word>INTO</Word> <Word>IS</Word> <Word>ISOLATION</Word> <Word>JOIN</Word> <Word>KEY</Word> <Word>LAST</Word> ...
長いのでGistに上げました。
Firebird 用xshd · GitHub
SyntaxHighlight のカスタマイズ2
コードビハインドに、読み込み処理を書いておきます。
public MainWindow() { InitializeComponent(); using (var reader = new XmlTextReader("sql.xshd")) { Editor.SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance); } }
結果
上記の通り、概ね思った通りになります。