2011年10月27日木曜日

◆アプリケーション開始時に処理を行う

アプリケーション開始時に処理を行うには、Applicationクラスの Application_Initialize()メソッドにに処理を書けば良さそうだ。

これらは、お約束通りpartialになっているのだが直接的にそのひな形を作る方法は無く、以下のような手順で代用する?

    1. 適当な画面をソリューションエクスプローラーでダブルクリックしてデザイナーを表示させる。
    2. 「ツールバー」「コードの記述」「アクセス制御メソッド」にて「画面名_CanRun」をクリック。
      image
    3. Applicationクラスが表示されるので追加された「画面名_CanRn」メソッドは削除(必要がなければ)
    4. 右上のドロップダウンから「Application_Initialize()」メソッドを選択して追加。
    5. 必要な処理を追加

今回は以下のように適当なメッセージを表示させてみた。

        partial void Application_Initialize()
{
System.Diagnostics.Debug.WriteLine("◆開始しますよ");
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(
() => { System.Windows.MessageBox.Show("◆開始しますよ"); });
}

image

2011年10月21日金曜日

◆Grid行の複数選択を可能にする

以下に解説がある。
How To Enable Multiple Row Selection In LightSwitch's Grids - MSDN サンプル ギャラリー

基本的には前回、以下でやったのと同様な方法でGridコントロールをFindして準備OKになったイベントを拾ってSelectionModeプロパティにDataGridSelectionMode.Extendedを設定してやるというパターンだ。
LightSwitch: ◆ConverterとFocusイベントを使って表示形式をカスタマイズする

SelectionModeプロパティの設定自体は問題ないのだが、サンプルの後半で選択状態に応じてボタンの有効・無効を切り替えている処理はなんとなくメタメタな気がする。

CanExecuteイベントハンドラーで有効無効をBool値で返すだけだと思うのだが、そもそも行選択の状態を変更したときにCanExecuteが発生してくれない。
image

新規行を選択したときに「編集」「削除」ボタンは無効になるのでCanExecuteとは別の仕掛けがあるのだろうか・・・。
image

CanExecute編集用のメニューも、状況に応じて違いがあり混乱する。
imageimage

デフォルトのボタンとユーザー追加したボタンで違うのかとも思ったがそうでも無さそう。(デフォルトのボタンでも画面テンプレートによって違う)

なんとなくどうでも良くなってきたので放置。

 

そもそも、これまではIDEでコントロールのプロパティをポチっと設定するだけでできていたものにたいして此の様な手間をかけるというのは方向性が間違っている。

現時点ではLightSwitchをそのような用途に使うべきでは無いのだろう。

SQLServer Management Studio のデータ参照・更新機能が簡単にカスタマイズ出来る様になった、っと捉えれば非常に便利なツールだ。

それ以上のことをやろうとすると我々一般ユーザーには他の開発ツール以上に敷居が高くなってしまうようだ。

2011年10月10日月曜日

◆ConverterとFocusイベントを使って表示形式をカスタマイズする

簡単に全体の機能を触ってみて気になるのが、表示項目の形式を簡単に変えられないこと。
また、入力項目のValidationも一応コーディングのインタフェースは標準で用意されているが、
image
昨今のアプリケーションであれば、ある程度のValidationはノンコーディングで可能になっていることを考えると、簡単さが売りと思われるLightSwitchで必ず(必須、最大長以外)コーディングが必要になるのは残念だ。

Validationはとりあえずコーディングインタフェースがあるから良いとしても表示形式を調整できないのはちょっと困る。

という事で、表示形式のカスタマイズ方法を探ってみた。
基本的にはLightSwitchもWPFアプリなのだろうからコンバーターとかを使うのかと思い、とりあえず以下のように実現した。
LightSwitchに関してはまだ情報も少なく、これが妥当なやり方なのかも判らないが一応こんな方法でも出来たよと言う事で。

<データ>

いつものように、NorthwindのCustomersをデータソースに使用。

<画面>

Customersをデータソースに、「一覧および詳細画面」のテンプレートを使って画面を作る。
コントロールツリーの「CustomersItemDetails」で「追加」ボタンをクリックし「新しいカスタムコントロール」をクリックする。

image

以下のネームスペースを展開して「TextBox」コントロールを追加する。
imageimage

ここでは「Country2」という名前にした。
image
 

ツールバーの「コードの記述」から「CustomersListDetail_Created」をクリックしてコードエディタを開く。

image

表示された「コードエディタ」にて以下のようなコーディングを追加した。

    public partial class CustomersListDetail
{
partial void CustomersListDetail_Created()
{
// ここにコードを書き込んでください。
this.FindControl("Country2").SetBinding(TextBox.TextProperty,
"Screen.Customers.SelectedItem.Country",
new CountryConverter(),
System.Windows.Data.BindingMode.TwoWay);

this.FindControl("Country2").ControlAvailable += Country2FieldAvailable;

}


private void Country2FieldAvailable(object sender, ControlAvailableEventArgs e)
{
((System.Windows.Controls.Control)e.Control).GotFocus += Country2GotFocus;
((System.Windows.Controls.Control)e.Control).LostFocus += Country2LostFocus;
}

private void Country2GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
var txtObj = (System.Windows.Controls.TextBox)sender;
txtObj.Text = (string)(new CountryConverter()).ConvertBack(txtObj.Text, null, null, null);

((System.Windows.Controls.TextBox)sender).SelectAll();
}

private void Country2LostFocus(object sender, System.Windows.RoutedEventArgs e)
{
var txtObj = (System.Windows.Controls.TextBox)sender;
txtObj.Text = (string)(new CountryConverter()).Convert(txtObj.Text, null, null, null);

}

class CountryConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return "(" + value + ")";
}

public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return (((string)value).Replace("(", "")).Replace(")", "");
}
}

}

6行目から9行目で「Country2」コントロールを検索し、Textプロパティに「Country」の値をバインドしている。
その時、コンバータとして自前の「CountryConverter」を指定。


また、Focusに応じても表示を切り替えたいので「GotFocus」と「LostFocus」にイベントハンドラーを登録する。
登録するタイミングとして、コントロールが有効になった後に行う必要があるようなので一旦11行目で「ControlAvailable」イベントを拾って、そこで登録処理を行う。


あとはConverterクラスを追加して「Convert」メソッドと「ConvertBack」を実装すればOKだ。
ここでは動作の確認だけなので便宜的に「Country」に括弧をつけて表示させている。


これで実行すると以下のような感じになる。


imageimage


とりあえず良い感じだが、ちょっとフォーマットしたいだけの要求には大げさな感じ。


もう少しなんとかならないものだろうか・・・。

2011年10月3日月曜日

◆承認、アクセス許可機能

ガイドツアーのサンプルで出てきた承認、アクセス機能を纏めておく。

<データ>

「Northwind」から「Categories」と「Products」を追加しそれぞれのデータに対して「編集可能グリッド画面」を作成する。
2011-10-03 16h08_58

<プロパテイ設定>

「ソリューションエクスプローラー」にて「プロパティ」をダブルクリックしてデザイナー画面を表示させる。
image

「画面ナビゲーション」タブをクリックすると以下のような画面が表示される。
2011-10-03 16h16_58

ここで、「タスク」フォルダにある画面は上記で作成した画面であり、実行時に表示される。
その下の「管理」フォルダにある画面(役割、ユーザー)は自動生成されたものであり通常は表示されない。
そこで、まずこれを開発時にも表示するようにしてみる。

この「管理」画面を表示するにはビルトインの「SecurityAdministration」権限が必要になっているので、開発ユーザーに対してその権限を許可する。
手順としては、「アクセス制御」タブをクリックし「フォーム認証を使用する」をチェックし、「SecurityAdministration」の「デバッグ様に許可」チェックボックスをONにする。(Windows認証でも良いと思うが、説明しやすいのでここではフォーム認証を使う)
image
また、同画面にて以下のように、画面に対する権限を作成する。
image

これで実行してみると、以下のように「管理」フォルダが表示されるのが判る。
また、開発時はログイン画面などは表示されず、自動的にデバッグユーザー(テストユーザー)でログインされる。(右下に表示)
image

試しに「ユーザー」をクリックして適当なユーザーを追加してみる。
2011-10-03 16h36_04

一旦保存し、次に「役割」画面にて「管理者」ロールを作成し「アクセス許可」に「セキュリティ管理」を追加。
image

同様に、「一般ユーザー」ロールを作成し「アクセス許可」に「カテゴリー権限」と「プロダクト権限」を追加する。
image

どうやら「役割」側から「ユーザー」は設定できないようなので(ロールから先に作れば良いのね・・)、ここで一旦保存し、またユーザーに戻る。
ここで、「test1」を「管理者」、「test2」を「一般ユーザー」にしてみる。(ロールが表示されない場合は最新の情報に更新をクリックすると良いようだ)
image

最後に「保存」ボタンをクリックする。

<コーディング>

実際に今作成した権限を利用して画面表示を制御する。

    1. 「ソリューションエクスプローラー」にて「EditableCategoriesGrid」画面をダブルクリックしてデザイナー画面を表示する。
    2. 「ツールバー」の「コードの記述」から「EditableCategoriesGrid_CanRun」メソッドを選択。
      image
    3. 表示されたコードエディタで以下のコーディングを追加。
              partial void EditableCategoriesGrid_CanRun(ref bool result)
      {
      // 結果を目的のフィールド値に設定します
      if(this.User.HasPermission(Permissions.ViewCategories))
      {
      result = true;
      }else{
      result = false;
      }
      }


      ちなみに、この時点で実行してみると「EditableCategoriesGrid」画面が表示されなくなるのが判る。

    4. 同様に、「EditableProdustsGrid」画面をダブルクリックしてコーディングを追加する。












<発行>


開発環境では簡単にユーザーを切り替える機能が見つからなかったので、とりあえず「発行して」から動作確認してみようと思う。(テストユーザーに権限を付与することで確認は可能だが)




    1. 「ビルド」メニューで「発行」をクリック

    2. 「クライアント構成」で「デスクトップ」を指定して「次へ」

    3. 「アプリケーションサーバーの構成」で「ローカル」を指定して「次へ」

    4. 「発行の出力」で「データベースに直接発行する」を指定して「次へ」

    5. 「データーベース接続」で接続文字列はデフォルトのまま「次へ」

    6. 「認証」では、先程すでに管理者を作成済みなので「アプリケーション管理者は既に作成されている」を選択し「次へ」(管理者を作成していない場合はここで指定する)

    7. 「必須コンポーネント」はデフォルトのまま「次へ」

    8. 「その他の接続」もデフォルトのまま「次へ」

    9. 「証明書の指定」もそのまま「次へ」

    10. 「概要」にて「発行」ボタンをクリック

<SETUP>


プロジェクトのフォルダに「Publish」というフォルダが作成されて「Setup.exe」が配置されているので実行してセットアップ。
image


セットアップが終わるとアプリケーションが起動されてログイン画面が表示されるのでログイン。
って、ログイン出来ない・・・。


ん~、どうやら開発時のユーザーをセットアップしてくれるなんてことはしないのね。(DBを確認してもUserテーブルは空だった)


仕方が無いので「発行ウィザード」に戻り、手順6にて「test1」ユーザーを追加したのちに再発行し、Setupを再実行。




「test1」でログインし、開発環境で行ったのとまったく同様に役割とユーザーを追加する。


追加した「test2」ユーザーでログインすると以下のような表示となる。(ちなみに、ユーザーの切替は再起動するしか無さげ)
2011-10-03 18h59_35