2013年1月28日月曜日

メニューのコマンドをViewModelに実装

1つ前の記事に記載したメニューの書き方から、実際にプログラム側で処理を行う部分を実験してみました。

MVVMモデルですとViewModelに相当する部分ですので、ファイル名は"MainWindowViewModel.cs"としています。

コマンドの記述としては、CanExecuteとExecuteが肝なのですが、こちらの書き方が諸説あるようで、まずは(調べると)ポピュラーと思われるパターンで実装してみました

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;     // IComand用
using System.Windows;            // Dialog表示用(表示しなければ不要)

namespace _130126Project
{
    public class MainWindowViewModel
    {
        class OkCommandImpl : ICommand
        {
          public bool CanExecute(object parameter) { return true; }
          public event EventHandler CanExecuteChanged;

          public void Execute(object parameter)
          {
            MessageBox.Show("コマンドが実行されました。");
          }
        }

        public ICommand OkCommand { get; private set; }



        // ViewModelのコンストラクタ
        public MainWindowViewModel()
        {
            // public ICommand型の公開プロパティに
      // OkCommandImplクラスのオブジェクトを設定
            this.OkCommand = new OkCommandImpl();
        }

    }
}

そして、コードビハインドと言われるコード(MainWindow.xaml.cs)のコンストラクタに
 DataContext = new MainWindowViewModel();
を記述します

    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();   // ここだけ追加
        }
    }

 とりあえずこれで
- メニューの"ファイル -  実行"を選択すると
- MainWindowViewModel.csのICommand型の"OkCommandの
動きます(これならprismを使わなくても動きますね)

もうちょっといい書き方があるかなぁと調べていると、
- DelegateCommandを使うと簡潔に記載できる
との記事が出てきます
さらに
- 以前はDelegateCommandを自作してたけど、prismに入っているから便利
という記事も出てきたりしました

いろいろ調べた末に↑のコードを以下のように変更して動作する事が出来ました
以下ではPrismを使っているのでコメントにある通りに、dllの参照設定を追加する必要があります
(面倒なので、2つ前の記事で解凍したprism関連のdllを全て選択してしまっていますが、使うのは以下のusingで記載したdllだけだと思います)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.ComponentModel;    // INotifyPropertyChange用
using Microsoft.Practices.Prism.Commands;    // prism用(予めdllを参照設定しておく)
using Microsoft.Practices.Prism.ViewModel;  // NotificationObject用

namespace _130126Project{
    public class MainWindowViewmodel : NotificationObject
    {
        private DelegateCommand<object> _okCommand;

        public DelegateCommand<object> OkCommand
        {
            get
            {
                return _okCommand ?? (_okCommand = new DelegateCommand<object>(
                    (param) =>
                    {   // Execute
                        MessageBox.Show("コマンドが実行されました");
                    },
                    (param) =>
                    {    // CanExecute
                         return true;    // 実行しない場合はfalseを返す。動的に変更可                    }
                ));
            }
        }
    }
}

動作としては以下のような感じのようです(デバッガでbreakさせた時の挙動)
0. View(xaml)の
     Command="{Binding OkCommand}"
  と
  DelegateCommand<object> OkCommand が紐づけ
1. オブジェクト作成時(プログラム起動時)にOkCommandのgetterにWPFがアクセス
  _okCommandはnullなのでDelegateCommandでnewします
2. menu表示時("ファイル"を押下してペロッと表示される瞬間)にWPFがCanExecuteを聞きに来る
  今回はtrueが返るのでメニューの"実行"も黒文字で表示される
3. "実行"を選択するともう一度"CanExecute"を聞きに来て、すぐにExecuteを実行
  結果、MessageBoxが表示される

"1"の部分が以前は自作されていたようでうすが、prismでサポートされたのでこちらの"DelegateCommand"を使うようになったようです

View-ViewModelのコマンドはこれで開通したので、次はModelとViewModelの接続について試していこうと思います





2013年1月27日日曜日

ChainLPの設定for Kindle PaperWhite

本来はソフト作成のtipsをメモっておこうと思ったのですが、早くも脱線
先月購入したKindleのChainLPでの変換設定メモです
(ChainLPは本ブログの題名とは無縁な素晴らしいソフトです)

表題で検索するといろいろな方が試したベストの設定が出てくるのですが、自分用に要点をメモ

準備
- ChainLPの他に、mobi形式を出力する場合はamaxonご提供のkindlegen.exeが必要
http://www.amazon.com/gp/feature.html?docId=1000234621&tag=wp-amazon-associate-20

入力
- PDFならarc、 jpegならdirを選択

出力
- kindleなのでmobiを選択
 (readerとかならePub)

サイズ
- 758 x 1024 : 通常

ページ補正
- 小説優先(文字が読みやすいとのこと)

ガンマ補正
- チェック / 自動レベルもチェック

これで"出力"ボタンを押すと出力先ディレクトリを尋ねられるので指定すれば変換開始

素晴らしいソフトです!!
(作者さんならびに設定で試行錯誤された先人にも感謝!)


メニューをつけてみる

Windows Formでは適当にツールボックスから貼るだけでメニューが生成できていましたが、WPFの場合はそうはいかない模様です

DockPanelのDockをTopにして配置していくのがよさそうです
以下の例では
- Menuを2項目配置 ("ファイル"と"オプション"がメニューバーに表示)
- それぞれに子要素を"MenuItem"で配置
- MenuItemは
  Header要素に、"メニューに表示される文字"
  実行させたい動作を"Command="{Binding コマンド名}" "
 として実装する模様
 画像なども貼れるようですが、一番シンプルなのはこんな感じで...

    <Grid>
        <DockPanel>
            <Menu Name="menuFile" DockPanel.Dock="Top">
                <MenuItem Header="ファイル">
                    <MenuItem Header="実行" Command="{Binding OkCommand}" />
                    <MenuItem Header="書き込み" Command="{Binding WriteCommand}"/>
                    <MenuItem Header="転送" Command="{Binding TransferCommand}"/>
                    <MenuItem Header="切り取り" Command="ApplicationCommands.Cut"/>
                </MenuItem>
                <MenuItem Header="オプション">
                    <MenuItem Header="設定" />
                    <MenuItem Header="情報" />
                </MenuItem>
            </Menu>
            <TextBox Name="textBoxWrite" DockPanel.Dock="Top"/>
        </DockPanel>
    </Grid>

Prismをインストールしてみる


最新はprism 4.1みたいなのでこちらからダウンロード
http://www.microsoft.com/en-us/download/details.aspx?id=28950

ダウンロードしたファイルをダブルクリックすると解凍されるので、好きな場所に置きます

システムに登録しておくとあとあと楽みたいだけど、とりあえずプロジェクトの"参照"->"参照の追加" -> "ブラウズ"でも設定できるようなのでこちらで(desktop下のdllをすべて選択して)追加

これで使えるようになる模様

※ ちなみに諸事情にて、VisualStudio10 for WindowsPhoneを入れた関係か予めBlendがinstallされています。もしかするとBlend(SDK)が入っていない場合はそちらを入れる必要があるかも....

はじめました

ブログ作ってみました
プログラム関連のメモを置いておこうかなと思っています