スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: スポンサー広告

(例外の)最終防衛ラインを引く

どんなに気をつけても、どんなにtry/catchをしても例外がアプリの外に漏れる事はある。
外に漏れる(未処理である)と、アプリが"落ちる"。それだけは避けたい!って時に実装(実行)するコード

Application.Current.DispatcherUnhandledException +=
new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(
ApplicationHelper.Current_DispatcherUnhandledException);

DispatcherUnhandledExceptionはイベントであり、未処理例外が発生した時に、イベントが励起される。
↓の記事がより詳しく書かれてますよ、はいOrz。
WPF アプリケーションの未処理の例外
この処理をしておけば、アプリそのものが落ちるってのは滅多にないんだけど…。
WPF4で困るのは、その例外情報(StackTrace)でさえエラーを特定できない時があるって事かな。
StackTrace情報がすべて、WPF内で始まり、WPF内で終わっているとかね…。
まあ、こっちのXAML記述が怪しかったりするんだろうけど、もうちょっと特定しやすい情報にしてくれと何度かおもった事がある。続きを読む
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

throw exとthrowは違うんだよ

C#例外処理でのthrowとthrow exの違い
「throw ex;」と書くと、本当の発生元の例外情報が消えてしまうのだそうで。
例外クラスを変えなければ、「throw;」が良いってことだな。
ところで、仕事上、「予期していない例外と開発者によってコード上でスローされる例外」を明確にしたい時がある。開発者によって投げられる例外って言うのは、「実行上では問題ないけど、業務上アウトな状態」が多い。例えば、

必須項目が入っていない
設定された値が、仕様で決められた範囲にない。
既に存在するキーで登録しようとする。

等。
で、よくやる手が、独自例外クラスの実装だったりする。
なお、独自例外クラスの実装は、上記理由の他にも、

例外内容がそのままを表示しても、ユーザは、次にどういうアクションを取れば良いのかわからない

時も、よく作成する。
この例外クラスに持たせる例外情報に必要なのが、

メッセージ
発生元の例外情報(例外をキャッチした時のみ)

となる、まあ、これは標準の例外クラスでも持っている情報。
ただ、この「エラーメッセージ」というところで悩むときもある。小さいプロジェクトや、開発ツール的な、表には出ないアプリなら、直接埋め込むの有りかなと思う。でも、規模が大きくなってくると、それではすまなくなる。
例えば、複数のクラスで同じメッセージで例外を発生させたい時とか。埋め込む分には、「コピペ」でOKなんだけど、変えるとなると大変になる。変えそこねるリスクが生まれる。
そんな理由から、メッセージはリソース化される事が多い。保管先は、データベースだったり、ファイルだったり、アセンブリリソースだったりするわけなんだけど、ユニークなキーを指定して、メッセージを取り出すという事に変わりはない。
という事で、上記2項目に加え、

メッセージキー(リソースキー)
サブメッセージ
メッセージパラメータ

等を加えて、エラー情報にする事が多い。
サブメッセージというのは、補助的なメッセージで、ユーザに次にこういうアクションとってねという情報を添えたり、このID、この番号がダメだよと知らせたりする。
メッセージパラメータは、メッセージを動的に変えたい時に使う。例えば、必須入力であるメッセージを作るとき、メッセージ本文は、

{0}を必ず入力してください。

で作り、状況に応じて、{0}に埋め込む文字列をパラメータとして持たせる、とか。
この独自例外クラスを標準の例外クラスと処理を区別しないと意味ないけど、まあ、それは気をつけるだけなんだよな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

MVVMのMessengerを理解&自作するという記事があったので。

参考にしたいが為のリンク。
MVVM:Messengerを理解するために自作してみた(1)
MVVM:Messengerを理解するために自作してみた(2)
MVVM:Messengerを理解するために自作してみた(3)
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMで、メッセージボックスを表示する(参)

(弐)の最後でも書いたけど、各メッセージコマンド用のプロパティ名を固定で持てるなら、まとめて実装するという手抜きができる。最初に設定するプロパティを文字列からboolに変える。
↓はInfoMsgCommandNameの代わりに設定するbool型の添付プロパティ。

/// <summary>
/// メッセージコマンドを使うかどうかを取得します。
/// </summary>
/// <param name="obj">対象オブジェクト</param>
/// <returns>true:使う</returns>
public static bool GetUseMessageCommand(DependencyObject obj) {
return (bool)obj.GetValue(UseMessageCommandProperty);
}

/// <summary>
/// メッセージコマンドを使うかどうかを設定します。
/// </summary>
/// <param name="obj">対象オブジェクト</param>
/// <param name="value">true:使う</param>
public static void SetUseMessageCommand(DependencyObject obj, bool value) {
obj.SetValue(UseMessageCommandProperty, value);
}

/// <summary>メッセージコマンドを使うかどうか</summary>
public static readonly DependencyProperty UseMessageCommandProperty =
DependencyProperty.RegisterAttached("UseMessageCommand",
typeof(bool),
typeof(WindowBehavior),
new UIPropertyMetadata(false,
OnUseMessageCommandPropertyChanged));

デフォルト値をfalseにして、XAML上でtrueに設定する事で、OnUseMessageCommandPropertyChangedメソッドが呼び出される。

/// <summary>
/// UseMessageCommandプロパティ値変更イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnUseMessageCommandPropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {

var window = dpObj as Window;

if (window != null && (bool)e.NewValue) {
window.DataContextChanged +=
new DependencyPropertyChangedEventHandler(Window_DataContextChanged);
window.Closed += new System.EventHandler(Window_Closed);
}

return;
}

DataContextChangedイベント用メソッド内の実装をガラっと変える。
タイトルとか設定できないなぁ…。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMで、メッセージボックスを表示する(弐)

コマンドクラスを実装したので、次は添付プロパティを実装する。
今回の実装方法として、コマンドクラスのインスタンスをVM側ではなく、View側で生成して、データバンディングさせる必要がある。
生成するキッカケを何にするか、と考えた時に、添付プロパティのプロパティ値の変更通知機能を使う事にした。

using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.ComponentModel;

namespace TawamureDays {

/// <summary>
/// ウィンドウ(Window)用ビヘイビアクラス
/// </summary>
public static class WindowBehavior {

/// <summary>
/// 情報メッセージ用コマンドを取得します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <returns>情報メッセージ用コマンド</returns>
private static ICommand GetInfoMessageCommand(DependencyObject obj) {
return (ICommand)obj.GetValue(InfoMessageCommandProperty);
}

/// <summary>
/// 情報メッセージ用コマンドを設定します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <param name="value">情報メッセージ用コマンド</param>
private static void SetInfoMessageCommand(DependencyObject obj, ICommand value) {
obj.SetValue(InfoMessageCommandProperty, value);
}

/// <summary>情報メッセージ用コマンド</summary>
private static readonly DependencyProperty InfoMessageCommandProperty =
DependencyProperty.RegisterAttached("InfoMessageCommand",
typeof(ICommand),
typeof(WindowBehavior),
new UIPropertyMetadata(null));


/// <summary>
/// 情報メッセージ用コマンド名(プロパティ名)を取得します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <returns>情報メッセージ用コマンド名</returns>
public static string GetInfoMsgCommandName(DependencyObject obj) {
return (string)obj.GetValue(InfoMsgCommandNameProperty);
}

/// <summary>
/// 情報メッセージ用コマンド名(プロパティ名)を設定します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <param name="value">情報メッセージ用コマンド名</param>
public static void SetInfoMsgCommandName(DependencyObject obj, string value) {
obj.SetValue(InfoMsgCommandNameProperty, value);
}

/// <summary>情報メッセージ用コマンド名(プロパティ名)</summary>
public static readonly DependencyProperty InfoMsgCommandNameProperty =
DependencyProperty.RegisterAttached("InfoMsgCommandName",
typeof(string),
typeof(WindowBehavior),
new UIPropertyMetadata(null,
OnInfoMessageCommandNamePropertyChanged));

/// <summary>
/// InfoMsgCommandNameプロパティ値変更イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnInfoMessageCommandNamePropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {

var window = dpObj as Window;

if (e.NewValue != null) {
window.DataContextChanged +=
new DependencyPropertyChangedEventHandler(Window_DataContextChanged);
window.Closed += new System.EventHandler(Window_Closed);
}

return;
}

/// <summary>
/// ウィンドウ終了イベントハンドラ
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void Window_Closed(object sender, System.EventArgs e) {
var window = sender as Window;
window.DataContextChanged -=
new DependencyPropertyChangedEventHandler(Window_DataContextChanged);
window.Closed -= new System.EventHandler(Window_Closed);
return;
}

/// <summary>
/// DataContext変更イベントハンドラ
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void Window_DataContextChanged(object sender,
DependencyPropertyChangedEventArgs e) {
var window = sender as Window;
var dataContext = e.NewValue;

//念のための後始末
var infoMsgCommand = WindowBehavior.
GetInfoMessageCommand(window) as InfoMessageCommand;

if (infoMsgCommand != null) {
infoMsgCommand.Clear();
infoMsgCommand = null;

WindowBehavior.SetInfoMessageCommand(window, null);
BindingOperations.ClearBinding(window,
WindowBehavior.InfoMessageCommandProperty);
}

//コマンド名(プロパティ名)
var msgCommandName = WindowBehavior.GetInfoMsgCommandName(window);

if (!string.IsNullOrWhiteSpace(msgCommandName)) {
//source側のプロパティと、InfoMessageCommandPropertyをバインディング
var binding = new Binding(msgCommandName) {
Source = dataContext,
Mode = BindingMode.OneWayToSource,
UpdateSourceTrigger =
UpdateSourceTrigger.PropertyChanged};
BindingOperations.SetBinding(window,
WindowBehavior.InfoMessageCommandProperty, binding);
//コマンド用インスタンスを生成して、設定します。
//この設定により、インスタンスがソース(VM側)に渡されます。
WindowBehavior.SetInfoMessageCommand(window,
new InfoMessageCommand(window));
}

return;
}
}
}
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMで、メッセージボックスを表示する(壱)。

MVVMパターンで、なにげにめんどくさいのがメッセージボックスを表示するという処理。
メッセージボックスはユーザに表示するもので、画面にあらわれてくるので、ビューなんだろうけど、実際に表示したい文字列を設定するのは、VM側となる。でも、MessageBox.ShowをVMには書きたくないし、Showメソッドの第1引数はウィンドウオブジェクトだし。
Livetなんかは、Messengerという機構を使って実現させている。じゃあ、Livetがないとどうにもならないか?といえばそうでもない。表題の通りではあるけど、添付プロパティとCommandを駆使すれば、できなくもない。
ここで記述するのは、仕事で使ったものそのものではなく、「こうもできたな」的な実装とする。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

トラブルは怖い。特に他人任せの部分は。

(続報)ヤフー子会社のファーストサーバ、WEBデータ消失

マスターどころか、バックアップも消去してしまった感じ。
サイトの閲覧できない会社も数社あり。
ミドルウエア(サイボウズ)等を利用もできなくなってたり。
データはおろか設定情報、メールの転送系すべて消失。
ファーストサーバの対応の悪さが不信を買いまくり。

もっとこうマスコミは大騒ぎしてもいいはずなんだけどな。
障害発生(6/20 17:30)から約54時間経過しても、復旧の目処が立っていない感じかな。
サーバー屋としてはアウトなんだけど、一体何やらかしたんだろ。消した範囲がでかすぎる。
消された側(会社)の担当者も生きた心地しないんだろうけど、やらかした人は、もっと生きた心地しないんだろうな。
サーバのメンテなんか一番気を使うところなんだけど。事前にフルバックアップとか取っていなかったのか、そのデータも消えたのか。
何にせよ、結末がどうなるか気になるところ。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: サーバ | コメント: 0 | トラックバック: 0

対Window用ViewModelをとりあえず作るか。(続き)

対Window用ViewModelをとりあえず作るか。
の続き。
各イベント用コマンドを稼働させるための添付プロパティを実装する。
Loadedイベント用は前に作ったので省略。

○Unloadedイベント用コマンド
Unloadedイベントは、ウィンドウの終了後に発生する。ただし、TabページやPage系とBindingすると、タブページの切り替え等でUnloadedイベントは発生する。

using System;
using System.Windows;
using System.Windows.Input;

namespace TawamureDays {

/// <summary>
/// FrameworkElement用ビヘイビアクラス
/// </summary>
public static class FrameworkElementBehavior {

/// <summary>
/// Unloaded用コマンドを取得します。
/// </summary>
/// <param name="obj">対象オブジェクト(FrameworkElement)</param>
/// <returns>Unloaded用コマンド</returns>
public static ICommand GetUnloadedCommand(DependencyObject obj) {
return (ICommand)obj.GetValue(UnloadedCommandProperty);
}

/// <summary>
/// Unloaded用コマンドを設定します。
/// </summary>
/// <param name="obj">対象オブジェクト(FrameworkElement)</param>
/// <param name="value">Unloaded用コマンド</param>
public static void SetUnloadedCommand(DependencyObject obj, ICommand value) {
obj.SetValue(UnloadedCommandProperty, value);
}

/// <summary>Unloaded用コマンド</summary>
public static readonly DependencyProperty UnloadedCommandProperty =
DependencyProperty.RegisterAttached("UnloadedCommand",
typeof(ICommand),
typeof(FrameworkElementBehavior),
new UIPropertyMetadata(null,
OnUnloadedCommandPropertyChanged));

/// <summary>
/// Unloadedプロパティ値変更イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnUnloadedCommandPropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {
var frwElement = dpObj as FrameworkElement;

if (frwElement == null) {
//FrameworkElementを継承していない
//クラスインスタンスは無視します。
return;
}

if (e.NewValue != null) {
if (!frwElement.IsLoaded) {
frwElement.Loaded += new RoutedEventHandler(FrwElement_Loaded2);
} else {
FrameworkElementBehavior.FrwElement_Loaded2(
frwElement,
new RoutedEventArgs {
Source = frwElement, Handled = false});
}
}
}

/// <summary>
/// Loadedイベントハンドラ用メソッド
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void FrwElement_Loaded2(object sender, RoutedEventArgs e) {
var frwElement = sender as FrameworkElement;
//登録したメソッドは削除しないと、メモリリークの元になる。
frwElement.Loaded -= new RoutedEventHandler(FrwElement_Loaded2);

frwElement.Unloaded += new RoutedEventHandler(FrwElement_Unloaded);

var window = Window.GetWindow(frwElement);
Action<object, EventArgs> closedHandler = null;

closedHandler = (sender2, e2) => {
frwElement.Unloaded -=
new RoutedEventHandler(FrwElement_Unloaded);

if (closedHandler != null) {
window.Closed -= new EventHandler(closedHandler);
closedHandler = null;
}
};

window.Closed += new EventHandler(closedHandler);
return;
}

/// <summary>
/// Unloadedイベントハンドラ
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void FrwElement_Unloaded(object sender, RoutedEventArgs e) {
var frwElement = sender as FrameworkElement;
//登録したメソッドは削除しないと、メモリリークの元になる。
frwElement.Unloaded -= new RoutedEventHandler(FrwElement_Loaded);

var command = FrameworkElementBehavior.GetUnloadedCommand(frwElement);

if (command != null && command.CanExecute(e)) {
command.Execute(e);
}
return;
}
}
}

Unloadedイベントへのハンドラ(メソッド)登録をプロパティ値変更時ではなく、Loadedイベント時に行う。
これは、Loaded時にClosedイベントをフックし、画面終了時にはUnloadedのコマンドを呼び出さないようにするための処置。

次、Closingイベント用コマンドを実装する。ClosingイベントはWindowクラスが持つので、WindowBehaviorに実装する。

using System.Windows;
using System.Windows.Input;
using System.ComponentModel;

namespace TawamureDays {

/// <summary>
/// ウィンドウ(Window)用ビヘイビアクラス
/// </summary>
public static class WindowBehavior {

#region ClosingCommandプロパティ

/// <summary>
/// Closingイベント用コマンドを取得します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <returns>Closingイベント用コマンド</returns>
public static ICommand GetClosingCommand(DependencyObject obj) {
return (ICommand)obj.GetValue(ClosingCommandProperty);
}

/// <summary>
/// Closingイベント用コマンドを設定します。
/// </summary>
/// <param name="obj">対象オブジェクト(Window)</param>
/// <param name="value">Closingイベント用コマンド</param>
public static void SetClosingCommand(DependencyObject obj, ICommand value) {
obj.SetValue(ClosingCommandProperty, value);
}

/// <summary>Closingイベント用コマンド</summary>
public static readonly DependencyProperty ClosingCommandProperty =
DependencyProperty.RegisterAttached("ClosingCommand",
typeof(ICommand),
typeof(WindowBehavior),
new UIPropertyMetadata(null,
OnClosingCommandPropertyChanged));

/// <summary>
/// ClosingCommandプロパティ値変更イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnClosingCommandPropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {

var window = dpObj as Window;

if (window == null) {
//Window以外を無視
//クラスインスタンスは無視します。
return;
}

if (e.NewValue != null) {
window.Closing += new CancelEventHandler(Window_Closing);
}
}

/// <summary>
/// ウィンドウ終了時イベントハンドラ(終了確定ではない)
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void Window_Closing(object sender, CancelEventArgs e) {
var window = sender as Window;

var command = WindowBehavior.GetClosingCommand(window);

if (command != null && command.CanExecute(e)) {
command.Execute(e);

if (!e.Cancel) {
window.Closing -= new CancelEventHandler(Window_Closing);
WindowBehavior.SetClosingCommand(window, null);
}
}
}

#endregion
}
}

コマンドパラメータとして、CancelEventArgsクラスのインスタンスを渡す。
Execute側でキャストして、e.Cancel=trueにすれば、画面終了をキャンセルできる。
Window用のViewModelを実装する。

using System;
using System.Windows;
using System.Windows.Data;

namespace TawamureDays {

/// <summary>
/// ウィンドウ用ViewModelクラス
/// </summary>
public sealed class MainWindowVM : BaseWindowVM {

#region BaseWindowVMメンバ

/// <summary>
/// Loadedイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected override void OnLoaded(object parameter) {
base.OnLoaded(parameter);
}

/// <summary>
/// Unloadedイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected override void OnUnloaded(object parameter) {
base.OnUnloaded(parameter);
}

/// <summary>
/// Closingイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected override void OnClosing(object parameter) {
base.OnClosing(parameter);
}

#endregion
}
}

実装した各コマンド用添付プロパティをXAML側に設定する。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="213" Width="385"
local:WindowBehavior.ClosingCommand="{Binding ClosingCommand}"
local:FrameworkElementBehavior.UnloadedCommand="{Binding UnloadedCommand}"
local:FrameworkElementBehavior.OnLoadedCommand="{Binding LoadedCommand}"
>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
</StackPanel>
</Window>

コードビハインド

using System;
using System.Windows;
using System.Windows.Data;
namespace TawamureDays {

/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window {

public MainWindow() {
InitializeComponent();
this.DataContext = new MainWindowVM();
return;
}
}
}

おおう。長い。まあ、これで起動時と終了時に必ず呼び出されるメソッドができるので、
OnLoadedメソッド→起動時の処理
OnClosingメソッド→終了時の処理。終了確認メッセージ表示も可能。
ってなるかな。
ああ、メッセージボックスってVM側であまり直接は呼び出さないな。
次はメッセージボックス系か。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

対Window用ViewModelをとりあえず作るか。

WPFで何かを作るにも、必ずウィンドウを作る。MVVMパターンで行くなら、まずそのウィンドウ用のVMが必要になる。というわけで、Window用、正確には、その中身(Content)用のVMを作る。まあ、これはPageクラスの事も考えているだけ。

using System;
using System.Collections.Generic;
using System.Linq;

namespace TawamureDays {

/// <summary>
/// ウィンドウ用ViewModelの基底クラス
/// </summary>
public class BaseWindowVM : BaseViewModel {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
public BaseWindowVM() : base() {
}

#endregion
}
}

BaseWindowViewModelでもいいんだけど、長いからViewModelをVMに略してBaseWindowVM。
この前作ったBaseViewModelを基底クラスにしている。
さてさて次に何を作るか。
ウィンドウ、ページ系だから、
・ロード時に呼び出されるメソッド
・アンロード時に呼び出されるメソッド
・終了時に呼び出されるメソッド
かな。
○ロード時に呼び出されるメソッド

/// <summary>
/// Loadedイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected virtual void OnLoaded(object parameter) {
}


○アンロード時に呼び出されるメソッド

/// <summary>
/// Unloadedイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected virtual void OnUnloaded(object parameter) {
}


○クロース時に呼び出されるメソッド

/// <summary>
/// Closingイベント発生時のメソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
protected virtual void OnClosing(object parameter) {
}

virtualなのは、派生クラスでオーバーライドするため。
当然の事ながら、これだけではどうにもならない。イベントと連携するためにコマンドを実装する。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

多重実行対策用コマンドを作る。

RelayCommandでは、対応できない連打による多重実行。ボタン押した回数分実行される。CanExecuteを見てくれよ!と言いたいけど、Executeの処理が終わってからチェックするので、正しく次が実行される。どうしようもない。
じゃあ、しょうがないですまないのが仕事なんだよ。締め(ある時点以前のデータを確定させ、編集できなくする)処理なんかを多重実行してほしくない(時間かかるし)。DataBindingには、IsAsyncというプロパティがあるんだけど、これはgetに時間がかかる場合のものらしい。
で、調べた結果、以下の記事を参考に作ることにしたのが、非同期実行型コマンド。
An Asynchronous Delegate Command for your WPF MVVM Apps - AsyncDelegateCommand
ようするに、Executeの実行をバックグラウンドで実行させ、その終了を待たずに、次の処理へ移るわけだ。
そうすることで、ボタンの無効化が発生し、多重実行を防止してくれる。
作ったクラスは上のリンクのクラスに以下の点を加えたもの。

・非同期実行には欠かせない、Dispatcherプロパティを追加します。
・メモリリーク対策として、内部をクリアするメソッド(Clear)メソッドを実装します。
・実行中の処理をキャンセルできても良いな。Cancelメソッドを実装する。
・実行中かどうか(実行可能かどうかではない)を取得するプロパティ(IsExecuting)を追加します。

検索や更新、時間のかかる処理をコマンドで実行させる時は、こっちを使うようにした。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMに必須なCommandクラスを作る。

Commandクラス=ICommandインターフェースを実装していること。
MVVMパターンでいうCommandクラスは、RelayCommandとかDelegateCommandとという名前で実装されるクラスが有名。
お?MSは、どうやら「RelayCommand」の方にするらしい。
RelayCommand クラス
↑のクラスは、VS2012以降から標準装備になる(?)ので、今は当然ない。
というわけで、他の記事にもあるように、Command用クラスを実装してみる。

using System;
using System.Windows.Input;

namespace TawamureDays {

/// <summary>
/// Command用クラス
/// </summary>
public sealed class RelayCommand : ICommand {

#region 内部変数

/// <summary>実行用メソッド</summary>
private Action<object> execute_ = null;

/// <summary>実行可否判定用メソッド</summary>
private Predicate<object> canExecute_ = null;

#endregion

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="execute">実行用メソッド</param>
/// <param name="canExecute">実行可否判定用メソッド</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null) {
execute_ = execute;
canExecute_ = canExecute;
}

#endregion

#region ICommand メンバー

/// <summary>
/// 実行可能かどうかを取得します。
/// </summary>
/// <param name="parameter">コマンドパラメータ</param>
/// <returns>true:実行可能</returns>
public bool CanExecute(object parameter) {
return canExecute_ == null ? true : canExecute_(parameter);
}

/// <summary>変更可否判定値変更イベント</summary>
public event EventHandler CanExecuteChanged;

/// <summary>
/// 実行します。
/// </summary>
/// <param name="parameter">コマンドパラメータ</param>
public void Execute(object parameter) {
execute_(parameter);
return;
}

#endregion
}
}

大体こんな感じかな。ただし、仕事ではこれで大丈夫、なんて事はなかった。
浮上した問題点は、いくつかあった。

①可否判定値変更イベントを明示的に発生できない。
 可否判定が働かないと、バインディングしているボタンの状態は変わってくれない。
②コンストラクタで渡すメソッド(ロジック)がそもそも問題があった。
③別スレッド内にて、このCommandを実行する時に問題が発生した。

これらの問題の詳細は追記で。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMパターンで、イベントをどうにかしよう。

WPFにも当然イベント機能があり、更にルーテッドイベントなんてのもある。
このイベントにハンドラ(リスナ)メソッドを登録すると、イベント発生時にフックされ、登録したメソッドが呼び出される。
ただ、このメソッド、基本的にコードビハインド側に作られる(そこでしか動かない)。
あれ?じゃあ、MVVMパターンでイベントを処理したい時どうすんだ?という話になる。仕事においては、以下の2つで対応した。

1.コマンド(ICommand)と添付プロパティ。
2.Expression BlendのTriggerActionを使う。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

既に標準装備だったとは・・・

データベース系の実装を如何にするかで悩んだ(2)
の(2)に書いたFactory系なんだけど、同じコンセプトのクラスがもう標準で実装されているっぽい。しかもその名前まんまで。
DbProviderFactory クラス
ADO.NET2.0かぁ。考えた仕様がほぼ同じだなぁ。そういうのあるって知ってたら、独自実装をいつまでも使わないのに、普通にショックだわ…Orz。ちなみに、考えたのは.NET1.1の頃。
ODBC、OleDb、SqlServerに加えて、OracleClientも可能かぁ。ああでもこれ、追加系のメソッドがないな。MySQL向けに実装した時、どうやって登録するんだろ?続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

WindowにModal起動かどうかを持たせて見る。

Windows.FormsではあったModalプロパティが、WPFにはない。
なので、色々調べてみた。
Where is Modal Property?
おお、これでいけるか?と思ったんだけど、Show()でもShowDialog()でも結果は変わらなかった。
何がダメなんだろ?と色々試してみたけど、結局他の手を打つことにした。
要は、添付プロパティで実装する事にした。

using System.Windows;

namespace TawamureDays {

/// <summary>
/// ウィンドウ(Window)用ビヘイビアクラス
/// </summary>
public static class WindowBehavior {

/// <summary>
/// Modal起動かどうかを取得します。
/// </summary>
/// <param name="obj">設定対象オブジェクト(Window)</param>
/// <returns>true:Modal起動, false:モードレス起動, null:不明(デフォルト)</returns>
public static bool? GetIsModal(DependencyObject obj) {
return (bool?)obj.GetValue(IsModalProperty);
}

/// <summary>
/// Modal起動かどうかを設定します。
/// </summary>
/// <param name="obj">設定対象オブジェクト(Window)</param>
/// <param name="value">true:Modal起動, false:モードレス起動</param>
public static void SetIsModal(DependencyObject obj, bool? value) {
obj.SetValue(IsModalProperty, value);
}

/// <summary>Modal起動かどうか</summary>
public static readonly DependencyProperty IsModalProperty =
DependencyProperty.RegisterAttached("IsModal", typeof(bool?),
typeof(WindowBehavior), new UIPropertyMetadata(null));
}
}

使い方は、自分で設定する。それだけ。

//モーダル起動
var window = new Window();
WindowBehavior.SetIsModal(window, true);
window.ShowDialog();


//モードレス起動
var window = new Window();
WindowBehavior.SetIsModal(window, false);
window.Show();

これは、終了時に、DialogResultプロパティを使えるかどうかの判定に使う。
※Show()メソッドで起動した時、DialogResultを設定して終了させようとするとエラーになるから。

var window = sender as Window;
var isModal = window.GetIsModal(window).GetValueOrDefault();

if (isModal) {
window.DialogResult = true;//trueはOK, falseはキャンセルを意味する。
}
window.Close();

いちいち設定するが面倒であれば、共通化する手段を探すしかないかな。
というか、標準でサポートしてくれよ…。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

LINQのOfTypeメソッド

任意の型を持つリスト(特殊な***Collectionや、IListで与えられるオブジェクト)から、特定クラスを引き出すためのLINQが、OfType<>メソッド。

using System;
using System.Linq;
...
ArrayList list = new ArrayList {1, 2L, 3, 4m, 5, 6D, 7, 8f};
var intList = new List(list.OfType<int>());
...

intListの中身は、{1,3,5,7}になる。キャストできないオブジェクトは無視される。
型でフィルタをかけるって感じかな。
intではなく、IDisposableなんかのインターフェースにも使えるので、それなりに便利。
なお、無視せずにキャストするためのメソッドも、Castという名前で用意されている。こっちの場合は、キャストできなければ、InvalidCastExceptionが発生する。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

ViewModelの基底クラスを作る。

MVVMパターンで必ず作るViewModelクラス。ViewModelを作るには、たいていINotifyPropertyChanged インターフェースを実装する必要がある。単純に実装するだけなら、↓のようになる。

using System;
using System.ComponentModel;

namespace TawamureDays {

/// <summary>
/// ViewModel基底クラス
/// </summary>
public class BaseViewModel : INotifyPropertyChanged {

#region INotifyPropertyChangedメンバ

/// <summary>プロパティ値変更イベント</summary>
public event PropertyChangedEventHandler PropertyChanged;

#endregion
}
}

でも、このインターフェースは、PropertyChangedイベントしか要求しない。
これだけで基底クラスというには、足りなさすぎる。
というわけで、継承したサブクラス内で使うメソッドを実装する。

using System;
using System.ComponentModel;

namespace TawamureDays {

/// <summary>
/// ViewModel基底クラス
/// </summary>
public class BaseViewModel : INotifyPropertyChanged {

#region INotifyPropertyChangedメンバ

/// <summary>プロパティ値変更イベント</summary>
public event PropertyChangedEventHandler PropertyChanged;

#endregion

#region protectedメソッド

/// <summary>
/// 指定されたプロパティ名で値変更を通知します。
/// </summary>
/// <param name="propertyName">プロパティ名</param>
protected void NotifyPropertyChanged(string propertyName) {
if (PropertyChanged != null) {
((PropertyChangedEventHandler)PropertyChanged)(
this, new PropertyChangedEventArgs(propertyName));
}
}

#endregion
}
}

NotifyPropertyChangedメソッドは明示的に変更を通知するメソッド。
基本的に、イベント発生はそのクラスの責任なので、protectedにしている。
PropertyChangedは、PropertyChangedEventHandlerにキャストする必要がある。
もう1つ実装しておきたいのが、IDisposableインターフェース。Windows.Formsではおなじみだけど、WPF4のコントロールにはあまり実装されていない。ただし、ViewModel側では、実装が必要だと思う。IDisposableは、後始末には最適なインターフェースなので。後始末をきちんとしないと、メモリリークの元になる。
で、IDisposable実装も含めた結果は以下のような感じ。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

さらにチェックを切り替えよう。

入力すると背景色が変わるTextBoxの続き
背景色の変更とともに、更にチェックボックスを切り替えてみる。

仕様:
TextBoxに入力有り→チェックON
TextBoxに入力無し→チェックOFF

CheckBoxのIsCheckedはbool型で、TextBoxのTextプロパティはstring型。型が違う。
string型をbool型に変えたい時に使うのがコンバータだ。
クラスにSystem.Windows.Data.IValueConverterインターフェースを実装する事で、コンバータとして使うことができる。上記仕様の動作となるように、コンバータクラスを作る。

using System;
using System.Windows;
using System.Windows.Data;

namespace TawamureDays {

/// <summary>
/// 文字列の内容(空文字かどうか)をBoolに変換するコンバータ
/// </summary>
[ValueConversion(typeof(string), typeof(bool))]
public sealed class StringToBoolConverter : IValueConverter {

#region 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,
System.Globalization.CultureInfo culture) {

if (value == null) {
return false;
}

return !string.IsNullOrWhiteSpace(value.ToString());
}

/// <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,
System.Globalization.CultureInfo culture) {
//モード「TwoWay」なら。実装する必要はあるけど…
return Binding.DoNothing;
}

#endregion
}
}

作成したコンバータクラスをDataBindingに利用する。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="213" Width="385">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<StackPanel.Resources>
<Style TargetType="TextBox">
<Setter Property="TextBox.Background" Value="AntiqueWhite"/>
<Style.Triggers>
<Trigger Property="TextBox.Text" Value="">
<Setter Property="TextBox.Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
<local:StringToBoolConverter x:Key="StringToBoolConverter"/>
</StackPanel.Resources>
<TextBox MinWidth="100" />
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Text,
ElementName=Text1,
Converter={StaticResource StringToBoolConverter}}"
Content="チェックだよ"/>
<TextBox MinWidth="100" Name="Text1"/>
</StackPanel>
</StackPanel>
</Window>

CheckBoxのIsCheckedプロパティにデータバインディングを仕掛けている。

{Binding Text, ElementName=Text1, Converter={StaticResource StringToBoolConverter}}

・"Text"はPathプロパティに渡すソース側のプロパティ。Path=Textと同じ意味になる。
・ElementNameは、XAML上のコントロールを参照できる。CheckBoxの下にあるTextBoxを指定している。
・Converterには、リソースで定義したStringToBoolConverterインスタンスを指定している。
StaticResourceに渡しているのはリソースキー。

Resourceの参照方法には、StaticとDynamicがある。役割は名前の通り。起動後に変更される可能性があるリソースには、DynamicResourceが使われる。
Skinなどでよく利用されるけど、気をつけて使わないと、メモリリークの元になる。なので、できるだけStaticResourceにする。
20120614_2
まあ、作ってはみたんだけど、こうやっちゃうと、CheckBoxのチェック状態が、DataContext側で把握できなくなるんだよな。チェックボックスそのものを押す事でも切り替えられるので、isCheckedの状態を把握しようと思うなら、この実装はペケなんだよな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

入力すると背景色が変わるTextBox

入力すると色が変わるTextBoxなんてのをStyleを使って実装してみた。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="213" Width="385">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<StackPanel.Resources>
<Style TargetType="TextBox">
<Setter Property="TextBox.Background" Value="AntiqueWhite"/>
<Style.Triggers>
<Trigger Property="TextBox.Text" Value="">
<Setter Property="TextBox.Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBox MinWidth="100" />
<TextBox MinWidth="100" />
</StackPanel>
</Window>

そんなに難しい話ではなく、入力がなければ、背景色を白にするというStyleTriggerをもたせただけ。
各プロパティを「TextBox.XXX」にしているのは、Styleが依存関係プロパティを直接使っている事を忘れないため。↓のような感じになる。
20120614_1
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

MVVMパターンで開発だよ。

WPFにおける開発パターン、かなぁ。
Model-View-ViewModel デザイン パターンによる WPF アプリケーション
よく参考にさせてもらった記事。

MVVMパターンの常識 ― 「M」「V」「VM」の役割とは?
1ページ目とかは非常に参考になるけど、ViewModelに関する説明で、Prismというフレームワークを使うこと前提で説明してるんだよなぁ。Messenger的な機能なんて、普通はないっす。
ダイアログは揮発性!と書かれているけど、画面起動前に処理したいとか、終わったら処理したいとか、色々あるんです。

第6回 「コマンド」と「MVVMパターン」を理解する
コマンドを理解する上で参考になります。

なお、色々なフレームワークが出回っています。
MVVM Light Toolkit
Prism
Livet
VS2010対応のスニペットやアイテムテンプレートまで用意してくれてたりするんだよなぁ。
ちなみに、自分は、どれも使わず、ほぼ自分たちで作った口です。ViewModelからViewへの連絡は、DataBindingとコマンドを駆使しました。
でも、小画面の呼び出し(画面遷移)だけは、VM側に実装しちゃったんだよなぁ。
フレームワークあると便利なんだけど、スニペットが、自分らのコーディング標準に合わない時とかあるし、バグがあってもそうそう手が出せないしで、結局自作への道に進んだんだよなぁと。思ったより大変だったOrz。
フレームワークは個人的には試してみたいけど、仕事で使う日はないかなぁ。
あ、でもMessenger的な機能は取り込んでみても良いかなぁ。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

DataBinding

・WPFの根幹の機能の1つ。
・ターゲット(コントロール)とソース(DataContext)のプロパティの値を紐付ける。連動させるとも言える。
・ソースをコントロールにすることも可能。
・バンディングは、XAML上でも、コード上でも可能。
・バインディングに失敗しても、起動時は例外にはならない。
 その後に、設定次第で例外が発生することもある。
・バインディングは、変更通知機能を通じてターゲット側へ値を反映させる。
・基本、コントロール:ソース=1:1あるいは、多:1
・マルチバインディングを使うことで、複数のソース側のプロパティを使ってバインディングできる。
DataBindingを使わないと、WPF使う意味ないかなとか。
Windows.Formsだと、コントロールの持つプロパティを直接変更していたけど、データバインディングを使うことでほぼそれがない。ビューとモデルの切り離しには欠かせない機能。
滅多に例外を発生させない割に、動作しない原因はたいていこいつだったりする。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

StyleとTemplate

Styleは、HTMLで言うところのCSS的な役割をする機能。ただし、似て非なる機能で、CSSのつもりで実装すると動かない事がままある。既存のUIに関わるプロパティを使い、なんらかの値の変化やイベントの発生をトリガーにして変化させる事もできる。
TargetTypeを指定することで、特定のコントロールに対して適用させたり、Keyを設定することで、そのキーを指定したコントロールにだけ適用することもできる。スタイルの継承等もできる。
Templateは、名前の通りテンプレート。Styleとは違い、コントロールの見た目を一から再構築することもできる。Styleよりも応用が利くけれど、標準のコントロール(ButtonやCheckBox)に使おうとすると、かなりの実装が必要になったりする。
Templateには、ControlTemplateとDataTemplateがあり、前者はコントロールありき、後者はデータ(DataContext)ありきのものとなる。カスタムコントロールを作ろうと思うなら、必ず使う機能とも言える。
この2つに加えて、SkinやTheme等があるけど、Skinはどう考えても、仕事では使わない。Skinで使う事になるDynamicResourceって、一つ間違えると、メモリリークの元になる。Themeは、カバーすべき範囲が広すぎて、一から作成ってのが無理な感じ(フリーのテーマが上がっているので、それを使うか、編集するか)。ただ、Theme適用すると、重くなる。
というわけで、StyleとTemplateを理解すれば、大抵のものは作れるかな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

ルーテッドイベント

WPF4には.NET標準のイベントだけでなく、ルーテッドイベントというイベント通知機構がある。
第3回 XAMLコードから生成されるプログラム・コードを理解する
要素ツリーを遡るのか下るのかはともかく、普通のイベントとは違い、イベント引数に色々な情報を持っている。定義の仕方も異なる。
このイベントは、拡張コントロールやカスタムコントロールを実装する上で非常に重宝する。
マウスで実際にクリックされた要素とかわかるしね。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

文字列の連結とか。

.NET1.1時代であれば、文字列の連結は、StringBuilderクラスの出番だった。
Javaの世界では、StringBufferだったかな。
普通のstringクラスがなぜ連結に向かないかは、Javaだろうと、.NETだろうと有名な話。
stringクラスはいわゆるイミュータブル(immutable)なクラス。
イミュータブル
一度インスタンスを作ると、値を変えることはできない。変えているように見えるが実は違うインスタンスなんだと。

var str = "...";
str = str.ToUpper();

1行目と2行目のstrはもう違うインスタンスだそうで。なので、連結を繰り返すと、ひたすら新しいインスタンスを作り、効率が非常に悪い。
その時に出番となったのがStringBuilderクラス。
だったんだけど、.NET4(2?)くらいから、便利なメソッドが実装されていた。
それが、stringクラスのConcatメソッド(static)。ぶっちゃけ、単なる連結なら、これで十分だ。

var strList = new [] {"1", "2", "3", "4", "5"};
var concat = string.Concat(strList); //結果は、"12345"

便利になったものだ。ところで、単なる連結なので、シンプルなのはいいけど、この文字列間に同じ区切り文字を挟みたい時、少々めんどくさいのだ。
例えば、パイプ(|)を挟みたい時なんか、こうするしかない。

var strList = new [] {"1", "|", "2", "|", "3", "|", "4", "|", "5"};
var concat = string.Concat(strList); //結果は、"1|2|3|4|5"

うん。めんどくさいし、DBから取得した任意要素数の配列やリストでは、これが通用しない。
というわけで、ちょっとだけ機能を付け足したメソッドを作成した。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 2 | トラックバック: 0

WrapPanel

折り返しできるStackPanel。ウィンドウのサイズに応じて自動で折り返してもいいなら、これ。
ListBox内部のPanelにこいつを指定したりすると、折り返すListBoxなんかが実装できる。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<WrapPanel>
<WrapPanel.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
</Style>
</WrapPanel.Resources>
<Button Content="1"/>
<Button Content="2"/>
<Button Content="3"/>
<Button Content="4"/>
<Button Content="5"/>
<Button Content="6"/>
<Button Content="7"/>
<Button Content="8"/>
<Button Content="9"/>
<Button Content="10"/>
</WrapPanel>
</Window>

20120607_2
ウィンドウのサイズに合わせて隠れないように折り返す。表示方向は、デフォルトで水平方向。
StackPanelのデフォルト(垂直方向)とは違うなぁ。StackPanel同様、縦方向にもできる。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<WrapPanel Orientation="Vertical">
<WrapPanel.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
</Style>
</WrapPanel.Resources>
<Button Content="1"/>
<Button Content="2"/>
<Button Content="3"/>
<Button Content="4"/>
<Button Content="5"/>
<Button Content="6"/>
<Button Content="7"/>
<Button Content="8"/>
<Button Content="9"/>
<Button Content="10"/>
</WrapPanel>
</Window>

20120607_1
なお、このボタンのサイズと別にWrapPanel側で、各アイテムの幅や高さの設定ができる。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<WrapPanel ItemHeight="150">
<WrapPanel.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
</Style>
</WrapPanel.Resources>
<Button Content="1"/>
<Button Content="2"/>
<Button Content="3"/>
<Button Content="4"/>
<Button Content="5"/>
<Button Content="6"/>
<Button Content="7"/>
<Button Content="8"/>
<Button Content="9"/>
<Button Content="10"/>
</WrapPanel>
</Window>

20120607_3
ItemHeghtプロパティを設定することで、1段目と2段目に余白をつける事ができる。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

JSON形式でオブジェクトをシリアライズする

自分が作ったクラスの情報等をファイルに出力したい時、たいていはシリアライズを行なってファイルに出力した。C#1.1の頃なんかは、XML形式へシリアライズ、あるいはバイナリ形式へシリアライズくらいしかなかった。
.NET3.5くらいからかな、JSON形式へのシリアライズが可能になった。
JSON自身は、別にC#に限った話ではない。でもそれなりに関わるもの。
最近、JSON形式でシリアライズしてみようと思って、とあるクラスを出力してみようと思ったんだけど、シリアライズできなかった。
おかしい。ちゃんと属性(Attribute)つけてるのに。

using System.Runtime.Serialization;

[DataContract]
public class ConcreteClass : BaseClass {

/// <summary>
/// コンストラクタ
/// </summary>
public ConcreteClass() : base() {
}


[DataMember]
public string KeyCode {
get; set;
}
}

実行時エラーになって、落ちてしまう。
なぜだ?と思ってエラー内容を見てみれば、BaseClassにDataContract属性がついてないからできない、と書いてある。
ちょっと待てい。それはダメなのか?ダメなんだ。ああもう、しょうがない・・・Orz。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

配列やリストにも欲しいメソッド

C#2.0あたりから文字列型には、IsNullOrEmptyというメソッドが実装された。
nullか空文字かを調べるためのメソッドなんだけど、意外に便利でよく使う。
文字列以外でも需要がありそうなのが、配列やリスト。欲しいっすよってんで実装してみた。

public static class Utils {

/// <summary>
/// 指定された配列やリストがnullあるいは要素数0の空かどうかを取得します。
/// </summary>
/// <typeparam name="TItem">アイテム要素の型宣言</typeparam>
/// <param name="list">リストや配列</param>
/// <returns>true:空あるいは要素数=0</returns>
public static bool IsNullOrEmpty<TItem>(IEnumerable<TItem> list) {
if (list == null) {
return true;
}

foreach (var item in list) {
return false;
}

return true;
}
}

LINQのCount()メソッドを使えなくもないけど、パフォーマンスを考えると、使わない方がいいかな。
こうすることで、お決まりのif文をメソッド1つで確認できる。

IList<int> list = ...;

if (!Utils.IsNullOrEmpty(list)) {
//...
}

int[] array = ...;

if (!Utils.IsNullOrEmpty(array)) {
//...
}

IEnumerable<>型にすることで、IList<>や配列にも対応できる。
IListやICollection、Array型なんかは受け付けないので、オーバーロードすれば、幅広く使えるかな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 2 | トラックバック: 0

Gridの複数の列、行でサイズを共有する

GridSplitterとは相容れないけど、こういう機能もGridにはある。
Grid.IsSharedSizeScopeという機能。
複数のRowDefinitionあるいは、ColumnDefinition間で幅や高さを共有するというもの。SharedSizeGroupと共に使う事で実現できる。
ただし、これは仕事上では使えなかった。だって、テンプレート内に入ってしまうと、もう共有ができなくなるから。
カスタムコントロール内でGridを使い、そのGridにSharedSizeGroupを仕掛けたとしても無視されてしまう。WPF4の仕様らしく、これをあてにして作った時はがっくりきたなぁ…。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

GridというPanel

Grid。格子状のパネル。行の数、列の数を指定でき、好きな位置にコントロールを配置できるパネル。
色々な事ができる為、StackPanelに比べればやや重い。
同じ行、列に設定されるコントロールは、上に重ねられていく。
重ねられないようにするために、マージン設定や、直下にStackPanel等を配置する。
今までのWindows.FormsライクなUIは、DockPanelの方が実装しやすい感じ。
Gridで使い出があるのは、GridSplitterとの連携で、サイズ変更したい時。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl>
<TabItem Header="Tab1">
<DockPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Background="Aqua"></Grid>
<GridSplitter Width="5" VerticalAlignment="Stretch"/>
<Grid Grid.Column="1" Background="Chartreuse"></Grid>
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</Grid>
</Window>

20120605_1

縦にスプリッタがあり、幅を自由に設定できる。ここでキモなのは、GridSplitterには、GridのColumn設定をしない事かな。
GridSplitterの為の列を設ける必要もない。下手に設定すると、思うように動かない。
次。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl>
<TabItem Header="Tab1">
<DockPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Background="Aqua"></Grid>
<GridSplitter Width="5" VerticalAlignment="Stretch"/>
<Grid Grid.Column="1" Background="Chartreuse"></Grid>
</Grid>
</DockPanel>
</TabItem>
<TabItem Header="Tab2">
<DockPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Background="Aqua"></Grid>
<GridSplitter Grid.Row="1"
Height="5"
HorizontalAlignment="Stretch"/>
<Grid Grid.Row="2" Background="Chartreuse"></Grid>
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</Grid>
</Window>

20120605_2

横にスプリッタがあり、高さを自由に設定できる。
キモなのは、
・縦の時と違い、GridSplitter用にGridの行を用意する事。
・あと、GridSplitterには、HorizontalAlignment="Stretch"設定が必要な事。
最後はおまけ。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

LINQでよく使うのは

LINQでよく使うのは、

フィルタとしてのWhereメソッド
射影、変換系としてのSelectメソッド
重複除外のDistinctメソッド
並び替えのOrderByメソッド

かな。なお、説明サイトでよくある、「var query = from x in array... 」という使い方はあまりしない。なぜか?LINQに馴染みのない開発者に優しくないから。
誰も彼もが最新技術をリアルタイムで勉強できるわけではないし、しているわけでもない。
なので、まだ「マシな方」である、拡張メソッドの方で使用する。
Whereメソッド:フィルタとして扱う。

var array = new []{1, 2, 3, 4, 5, 6, 7, 8, 9};

foreach (var x in array.Where(elem => elem > 5)) {
}

Selectメソッド:射影(特定プロパティのみ抽出)や変換(値を更に変換)

var array = new []{1, 2, 3, 4, 5, 6, 7, 8, 9};

foreach (var x in array.Select(elem => elem + elem)) {
}

両方使う場合は、Where(...).Select(...)の順番で使う。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

ボタンを並べるには良いStackPanel

Panel系でもシンプルな作りと速さがウリのStackPanel。小難しい事はできないので、専らボタンを並べるのに使っている。

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="MinWidth" Value="100"/>
<Setter Property="Margin" Value="5,1,5,1"/>
</Style>
</Window.Resources>
<Grid>
<DockPanel LastChildFill="False">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
<Button>登録</Button>
<Button>更新</Button>
<Button>削除</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button>前へ</Button>
<Button>次へ</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Left">
<Button>メニュー1</Button>
<Button>メニュー2</Button>
<Button>メニュー3</Button>
<Button>メニュー4</Button>
<Button>メニュー5</Button>
</StackPanel>
</DockPanel>
</Grid>
</Window>

単に並べるだけなら、StaclPanelが良い。Gridだと、列だの行だのと設定する必要があるし、妙に重なるしね。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。