Friendly ハンズオン 11 WPF用上位ライブラリ
今回はWPFのGUIコントロールの操作です。
これは、めとべやさんと協力して作っています。ソースコードはこちらです。
Roommetro/Friendly.WPFStandardControls · GitHub
現在以下のものに対応しています。
WPF用は近いうちに機能追加していこうと思っています。
追加したらまたブログに書きますねー。
対応表
System.Windows.Controls | Friendly.WPFStandardControls |
---|---|
ButtonBase | WPFButtonBase |
ComboBox | WPFComboBox |
ListBox | WPFListBox |
ListView | WPFListView |
MenuBase | WPFMenuBase |
MenuItem | WPFMenuItem |
ProgressBar | WPFProgressBar |
RichTextBox | WPFRichTextBox |
Selector | WPFSelector |
Slider | WPFSlider |
TabControl | WPFTabControl |
TextBox | WPFTextBox |
ToggleButton | WPFToggleButton |
TreeView | WPFTreeView |
TreeViewItem | WPFTreeViewItem |
Calendar | WPFCalendar |
DatePicker | WPFDatePicker |
DataGrid | WPFDataGrid |
※System.Windows.Controls.Primitivesのクラスも混じっています。
ハンズオンの練習用プロジェクト
こちらからダウンロードお願いします。
Ishikawa-Tatsuya/HandsOn11 · GitHub
ビルドして対象アプリを起動すると、こんな感じです。
OKボタンを押すと、入力内容がメッセージボックスに表示されます。
DataGridの中には、このデータがリストで入っています。
public enum Language { C, CPP, CS } [Serializable] public class Member { public string Name { get; set; } public Language Language { get; set; } public bool IsProgramer { get; set; } public override string ToString() { return Name + ", " + Language + ", " + IsProgramer; } }
Testプロジェクトは参照設定も終わっています。
自分のテストプロジェクトで使う場合は、NugetからFriendly.WPFStandardControlsとFriendly.Windows.NativeStandardControlsを取得してください。NativeStandardControlsはメッセージボックス操作に使います。前回も書きましたが、WPFでもメッセージボックスはネイティブのものが使われているのです。
WPFTest.csコードはこれです。これに、書き足していってください。
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Codeer.Friendly; using Codeer.Friendly.Dynamic; using Codeer.Friendly.Windows; using Codeer.Friendly.Windows.NativeStandardControls; using RM.Friendly.WPFStandardControls; using System.Diagnostics; using System.Windows; using WpfTarget; using Codeer.Friendly.Windows.Grasp; namespace Test { [TestClass] public class WPFTest { WindowsAppFriend _app; dynamic _main; [TestInitialize] public void TestInitialize() { _app = new WindowsAppFriend(Process.Start("WpfTarget.exe")); _main = _app.Type<Application>().Current.MainWindow; } [TestCleanup] public void TestCleanup() { Process.GetProcessById(_app.ProcessId).CloseMainWindow(); } } }
ハンズオン開始
TextBox
まずはTextBoxです。使い方はWinFormsのものと同じですね。
TextBoxの特定はx:Nameでやっています。テスタビリティーを上げるためにプロダクトの方で、全てのコントロールには名前を付けているのですね。
[TestMethod] public void TestTextBox() { var _textBoxCompanyName = new WPFTextBox(_main._textBoxCompanyName); _textBoxCompanyName.EmulateChangeText("Codeer.ltd"); Assert.AreEqual("Codeer.ltd", _textBoxCompanyName.Text); }
DatePicker
はい。DatePickerも簡単に操作できますね。
[TestMethod] public void TestDatePicker() { var _dateTimePickerFounding = new WPFDatePicker(_main._dateTimePickerFounding); _dateTimePickerFounding.EmulateChangeDate(new DateTime(2011, 3, 14)); Assert.AreEqual(new DateTime(2011, 3, 14), _dateTimePickerFounding.SelectedDate); }
DataGrid
DataGridです。編集方法はText、ComoboBox、CheckBoxに対応しています。その他のものが必要であれば、そんなに難しくはないので、各自で対応してみてください。(基本部分押さえていれば出来ると思います。)
データの検証はここでは、対応するデータでやっていますね。セル文字列を取るインターフェイスもあるのですが、こっちの方が手っ取り早いので。
WPFDataGridのthis[index]はdynamicで相手プロセスの参照が返ってきます。それを実データにキャストすることによって、相手プロセスからコピーを転送してきているのですね。
[TestMethod] public void TestDataGrid() { var _grid = new WPFDataGrid(_main._grid); _grid.EmulateChangeCellText(0, 0, "ishikawa"); _grid.EmulateChangeCellComboSelect(0, 1, 2); _grid.EmulateCellCheck(0, 2, true); //1つめのデータアイテムのコピーを取得 Member member = _grid[0]; Assert.AreEqual("ishikawa", member.Name); Assert.AreEqual(Language.CS, member.Language); Assert.AreEqual(true, member.IsProgramer); }
Button
ボタン操作です。OKボタンを押すと入力内容がメッセージボックスに表示されます。値の設定は、ここまでに書いたものを使い回しています。
表示されるメッセージボックスはWPFでもWin32のものですね。NativeMessageBoxを使用して操作します。
[TestMethod] public void TestButtonBaseAndMessageBox() { //値の設定 TestTextBox(); TestDatePicker(); TestDataGrid(); //非同期処理でボタンを押す var _buttonOK = new WPFButtonBase(_main._buttonOK); Async a = new Async(); _buttonOK.EmulateClick(a); //メッセージボックス(ネイティブ) var window = new WindowControl(_main); var msg = new NativeMessageBox(window.WaitForNextModal()); Assert.AreEqual("Codeer.ltd\r\n2011/03/14\r\nishikawa, CS, True", msg.Message); msg.EmulateButtonClick("OK"); //非同期処理完了待ち a.WaitForCompletion(); }
GUI要素の特定は?
それはもうx:Nameが一番確実ですw
テスタビリティーを向上させることを考えればx:Nameを付けるのも、なんら恥じることはありません!
・・・
でもまあ嫌な人もいますよね。
Bindingから特定してみる。
結局ですね、相手プロセスでできることは全て可能なのです。だから特定方法も好きなように作ってもらえばOKです。で、その一例としてBindingから特定するサンプルを作ってみました。
Ishikawa-Tatsuya/Friendly-SearchByBinding · GitHub
これは、もう少し洗練させて、Friendly.WPFStandardControlsに取り込もうと思っています。乞うご期待!
自分で好きに作れます。
繰り返しますが、特定方法はFriendlyの基本部分とWPFを理解していれば好きなように作れます。
何かいい方法思いついた人はプルリクお願いします。
このブログへのコメントでもOKです!
アイデア、要望レベルでも構いません。よろしくです。