2013年2月23日土曜日

テンプレートを使ってみる

参照の追加やusingの記述などで同じような記述を毎回するのは面倒なので、VisualStudioのテンプレート機能を使ってみました

カスタマイズはいろいろ出来るようですが、理解できなかったのでとりあえず...
1. 適当なソリューションを新規作成する("Templete"という名前で良い...特に後で影響しないようなのでなんでもよいようです)
2.  参照やusingの記述をしたり、毎回追加するファイルを追加しておくなどを行う(MVVMなら***ViewModel.csとか)
3. "ファイル" -> "テンプレートのエクスポート"を選択
4. ダイアログが出るのでひたすらデフォルトで"次へ"
5. どこかにzipファイルで出力される模様
> 追記 : MyDocumentsの↓の位置にzipファイルとして作成される
> C:\Users\xxxxx\Documents\Visual Studio 2012\Templates\ProjectTemplates\Visual C#
> 別のマシンで使う場合は同じ場所にコピーすれば使えるみたい

使う場合は、ふつーに新規プロジェクトの作成をしようとすると↑で作成したテンプレートが下の方に表示されるのでそちらを選択すると、いい感じでTemplateで作成した内容がデフォルトになったプロジェクトが生成される模様
(namespaceなどは新規作成にあわせてくれるという意味で)

カスタマイズは奥が深いみたいですが、↑の程度でも適当に使えるので活用してみようかと思います



2013年2月7日木曜日

XAML内でのデータバインド

最も簡単な例として、定番の"スライダーとテキストをbind"してみました

<Window x:Class="_130206_xamlDataBind.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Slider VerticalAlignment="Top" HorizontalAlignment="Center" Width="300" Margin="10"
                    Name="slider" Value="{Binding textValue}" />
            <TextBlock VerticalAlignment="Top" HorizontalAlignment="Center"
                    Text="{Binding ElementName=slider, Path=Value}" />
        </StackPanel>
    </Grid>
</Window>

2013年2月4日月曜日

BehaviorでViewからViewModelのコマンドを実行&パラメータ渡し

ViewからViewModelのコマンドを実行する際に、Behaviorというものを使う方法があるとのことですので動かしてみました(丸パクリですが...)

手順としては
1. 参照設定の追加
Blendの機能なので、Interactivity.dllを参照する
"プロジェクトの参照設定"の"ブラウズ"にて"参照(B)"から
C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries
の以下の2つのdllを追加
Microsoft.Expression.Interactions.dll
System.Windows.Interactivity.dll
を選択して"追加"する

2. ***Behavior.cs を作成(ここにbeheviorの処理を書いていきたい)

3. usingを追加
using System.Windows.Interactivity;         // 追加
using Microsoft.Expression.Interactivity;   // 追加

4. 監視対象の型のBehaviorを継承したクラスを作成
using が足りないので以下を追加
using System.Windows.Controls;      // コントロール名称を参照する為
using System.Windows;               // DependencyPropertyの定義

監視対象の型のBehaviorを継承したクラスを作成
    public class TestBehavior : Behavior<Button>

5. 依存関係プロパティの定義と登録
作成したクラス内に依存関係プロパティを登録するコードを追加
戻りは"依存関係プロパティ識別子"で"後でプログラムで値を設定したり、メタデータを取得したりする際に、この識別子を使用して依存関係プロパティを参照できます"とのこと
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message" , typeof(string), typeof(TestBehavior),
                            new UIPropertyMetadata(null));

6. (登録される)依存関係プロパティ
        // 公開プロパティ
        private string _message;
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

7. 独自ハンドラ(イベント発生時にやりたいこと)追加
        private void Aleart(object sender, EventArgs e)
        {
            if(!string.IsNullOrEmpty(this.Message)){
                MessageBox.Show(this.Message);
            }
        }

8. アタッチ・デタッチ時のハンドラを登録
        /// <summary>
        /// アタッチされた時の処理
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Click += Alert;
        }

        /// <summary>
        /// デタッチされた時の処理
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Click -= Alert;
        }
9. xamlにBehaviorを呼び出す処理を記載
            <Button Content="Button" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="75">
                <i:Interaction.Behaviors>
                    <local:TestBehavior Message="メッセージを渡す"/>
                </i:Interaction.Behaviors>
            </Button>


とりあえずこれで
- ボタンをクリックした時にBehavior側の処理を呼び出す
という事が出来るようです

BreakPointを適当に張ってみると
1. 起動時にアタッチのハンドラが呼ばれる
  ここで"ボタンクリックイベントにメソッドが登録される"模様
2. ボタンを押下すると登録されたメソッドが呼ばれる
  この時、すでに依存関係プロパティにはxaml側の
  "Message="メッセージを渡す"
  という部分が反映されている
という動きの模様

動かしたソースは以下の通り
TestBehavior.cs側
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Interactivity;         // 追加
using Microsoft.Expression.Interactivity;   // 追加

using System.Windows.Controls;      // コントロール名称を参照する為
using System.Windows;               // DependencyPropertyの定義

using System.Diagnostics;

namespace BehaviorTest
{
    public class TestBehavior : Behavior<Button>
    {
        // 依存関係プロパティの登録
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(TestBehavior),
                                        new UIPropertyMetadata(null));

        // 登録される依存関係プロパティ
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }
       
        /// <summary>
        /// アクションハンドラの記載(ボタン押下時に実行)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Alert(object sender, EventArgs e)
        {
            MessageBox.Show(this.Message);
        }

        /// <summary>
        /// アタッチされた時の処理
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Click += Alert;
        }

        /// <summary>
        /// デタッチされた時の処理
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Click -= Alert;
        }
    }
}


xaml側のコード
<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
       
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:BehaviorTest"
        >
    <!-- 上記Title以下の2行追加 -->
    <Grid>
        <StackPanel>
            <Button Content="Button" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="75">
                <i:Interaction.Behaviors>
                    <local:TestBehavior Message="メッセージを渡す"/>
         <!-- ↑の"Message"がコードにバインドされている模様 -->
                </i:Interaction.Behaviors>
            </Button>
        </StackPanel>
    </Grid>
</Window>


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)が入っていない場合はそちらを入れる必要があるかも....