2017年4月23日日曜日

10万PV突破

初めての投稿から3年弱、皆様に支えられてつい最近10万PVを突破いたしました。
ありがとうございます。
趣味でやっているプログラミング関係のことを中心にしたブログですので、かなり不定期の更新になっています。下手したら更新が数か月開くこともザラでした。

ですが、最近はだいたい1日当たり100~200PVほどいただいているようです。1か月にしてだいたい4500PV程度。更新頻度が低く、しかも自分の備忘録としての側面が強いブログにしてはかなりPVが大きなほうだと思います。

参考までに、ここ1か月のPVランキングを示すと

1位WPFのScrollViewerやScrollBarのスクロール位置を同期させる2015/01/16339PV
2位ポケモン「サファイア」の時計を復活させる2016/01/22308PV
3位プロキシ設定とレジストリ2015/11/09231PV
4位WPFでタスクトレイ常駐型アプリを作る2015/11/12195PV
5位非同期処理とAggregateException2014/10/15167PV

てな具合です。

ScrollViewerの記事はここのところずーっと首位です。これがヒットするとは思っていませんでしたが、実はそれなりに需要があった記事なんですかね。
2位のポケモンのソフトのRTCをいじる記事は、最近PVをどんどん上げています。たぶん、近いうちにScrollViewerの記事を抜くのではないかなと思います(週単位でランキングを作るとすでに抜かれています)。記事を書いた当時はまだ任天堂はGBAソフトの電池の交換をやってくれていましたが、今はもうそのサービスは終了したそうなので、復活させるなら否が応でも自分でどうにかしなきゃいけないという背景もあるのかもしれません。
プロキシの記事は、自分がネットにソフトを初めて公開した件にかかわる話ですので、PVを伸ばしてくれていることはとても嬉しいです。

てな具合で、今後もぼちぼち自分のペースでブログを書いていこうと思います。
今後ともよろしくお願いいたします。

2017年4月22日土曜日

Visual Studio 2017でXamarin.Forms入門

「申し訳ないがJavaはNG」

この言葉を座右の銘に置く私としては、常にAndroidアプリ開発は戦いです。
AndroidはJava開発が最も基本で、C#で開発するにはXamarinなどの環境が必要です。

Xamarinは昔は有料だったうえ、ドキュメンテーションも少なく非常にとっつきにくいものでした。しかし、Visual Studio 2015にはオプションでXamarinをインストールできるようになり、ついに2016年にはMicrosoftに買収され、Visual Studio 2017ではモバイル開発の中核に置かれるようになりました。

というわけで、私もXamarin初心者ですが、VS2017もインストールしたことだし本格的にいじってみようと思います。

Visual Studio 2017のインストール時にXamarin関係のオプションを選択してインストールすると、プロジェクトテンプレートにXamarin.Formsが現れます。
そうするとテンプレートの選択が出てきます。
空のアプリを選択してOKを押します。
そして、プロジェクトをビルドして実行すると…
見事にエミュレーター上でAndroidアプリが動きました。

しかし、このプロジェクトテンプレートには問題が1つあります。
上の画像にも書きましたが、最初のページに相当する「MainPage.xaml」がどのプロジェクトにも含まれていません。
そのため、Visual Studioがコードの依存関係等を理解できずに、IntelliSenseがほとんど働きません。編集しているとコードのいたるところに参照が解決できずに波線が引かれます。とても鬱陶しいです。

この解決には苦労しましたが、とりあえず次のようにやるとできるようです。

まずは、ソリューションにXamarin.Forms用のPCL(Portable Class Library)を追加します。
次は各プラットフォームのプロジェクトでこのプロジェクトへの参照を追加します。
さっき追加したプロジェクトに適当なMainPage.xamlを作ります。
このテンプレートには、XAMLだけでなくコードビハインドにも余計なコードが書いてあるので注意してください。コードビハインドで架空のViewModelクラス(ContentPageViewModel)をインスタンス化しようとしてくるのでコンパイルエラーが出ます。
public partial class App : Application
{
    public App ()
    {
        InitializeComponent();

        //MainPage = new XamarinFormsTest.MainPage();
        MainPage = new XamarinFormsTest.PCL.Views.MainPage();
    }

    protected override void OnStart ()
    {
        // Handle when your app starts
    }

    protected override void OnSleep ()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume ()
    {
        // Handle when your app resumes
    }
}
最後はApp.xamlのコードビハインドでMainPageのインスタンスを自分が追加してやったPCLのほうへ書き換えてやればおkです。もとあったMainPage.xamlはいらないので削除してしまってもよいでしょう。
これでMainPageをPCL上に移動することに成功しました。

PCL上にUIを置けるということは、Nugetなどを活用して適当なライブラリを入れることもできるということですので、例えばXamarin.Formsに対応しているMVVMライブラリ「Prism」を入れてみましょう。
そうすれば、ほとんどWPFと変わらずにXAML+C#でAndroidアプリを開発することができます。
このアプリでは、スライダーを 動かすとそれに追従して上に表示されている数字が変わります。「ADJUST TO 50」ボタンを押すと数字とスライダーが50の位置に移動します。
XAML+C#のデータバインディングのデモをするにはこれくらいやれば十分でしょう。

例えばコントロールの配置が「HorizontalOptions」「VerticalOptions」とかいう名前のプロパティだったりと、若干WPFと違うところもありますが、まあこれくらいならフィーリングでわかるレベルでしょう。
あとはXAMLデザイナーでリアルタイムに配置の絵が表示される機能は内容ですが、この程度ならば個人的にはまあギリギリ許容できます。

これくらいWPFの開発にそっくりだと、普段からWPFで開発している身としてはとてもありがたいですね。

というわけで、いろいろといじってみようと思います。はい。

2017年4月18日火曜日

最強のWPF MVVMインフラ「Livet」をVS2017で使う

世の中的にはWindows開発と言えばUWPとかなのかもしれませんが、まだまだレガシーなWindowsデスクトップアプリが滅びる様子はありませんよね。
そのレガシーな中でも最も近代的なプラットフォームと言えばやはりWPFで、WPFでアプリケーションを作るのならばやはりLivetは欠かせません。

Livet - ProjectHome

しかし、LivetはVS2015対応としてリリースされたver.1.3を最後に更新されておりません。
作者自身もVS2015対応版がLivet 1.xの最終リリースとする旨の発言をしており、今後はLivet2を開発すると言っています。

ugaya40/Livet2 - GitHub

しかし、現時点でLivet2のLastest commitは2015年8月。Livetの最大の武器ともいえるプロジェクトテンプレート付きのインストーラはおろか、正式リリースさえされていない状態です。このような状況ではVS2017対応は絶望的です。

そうすると、何とかして自力でLivetをVS2017にインストールしなければなりません。

さて、VS2013とVS2015がリリースされた直後も、自力でLivetのプロジェクトテンプレートを組み込んでいた漢たちはいました。

最強のWPF MVVMインフラ「Livet」をVS2013で使う
最強のWPF MVVMインフラ「Livet」をVS2015で使う

Livet自体もこの時からほとんど進んでいませんし、こちらのページで紹介されているバッチファイルをちょっと改造すればいけるでしょう。

の前に、コードスニペットを改良しておきます。
本来、その改良はVS2015対応でやるべきでした。

VS2015と同時にリリースされたC#6でnameof演算子が導入されています。この、INotifyPropertyChangedインターフェースの実装に使ってくださいと言わんばかりの機能を通知プロパティのスニペットに使わない理由は無いでしょう。
ちなみに、.NET4.5からはCallerMemberName属性を使うことで自動的に呼び出し元のプロパティ名を引数としてメソッドに引き渡す機能があるので、通知プロパティの実装にそれを使う人も多いようです(Livetももちろんそれに対応しています)。しかし、「書いてもいないものが勝手に生成される」という気持ち悪さから私はこの言語機能を使いたくないので、nameofを使ったコードを書くことにしています。

というわけで、GitHubからダウンロードしたLivet-master\Installer\Files\Snippets内のLivetProperty_NET45_CSharp.snippetは削除して、LivetProperty_NET40_CSharp.snippetをnameof演算子に書き換えておきましょう(VBも必要があればやっておくといいと思います)。
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2008/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Livet プロパティ</Title>
      <Shortcut>lprop</Shortcut>
      <Author>Livet Project</Author>
      <Description>プロパティを作成します</Description>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Imports>
        <Import>
          <Namespace>Livet</Namespace>
        </Import>
      </Imports>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>プロパティの型</ToolTip>
          <Default>string</Default>
        </Literal>
        <Literal>
          <ID>name</ID>
          <ToolTip>プロパティ名</ToolTip>
          <Default>MyProperty</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[
#region $name$変更通知プロパティ
private $type$ _$name$;

public $type$ $name$
{
get
{ return _$name$; }
set
{ $end$
if(_$name$ == value)
return; 
_$name$ = value; 
RaisePropertyChanged(nameof($name$));
}
}
#endregion
]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
最後に、上記のVS2015版のサイトのbatファイルの「2015」を「2017」に置換してから実行してやればOKです。
@echo off
cd %~d0%~p0

@echo on
echo copy snippets
xcopy /I /Y .\Files\Snippets\*_CSharp.* "%UserProfile%\Documents\Visual Studio 2017\Code Snippets\Visual C#\My Code Snippets\Livet"
xcopy /I /Y .\Files\Snippets\*_VB.* "%UserProfile%\Documents\Visual Studio 2017\Code Snippets\Visual Basic\My Code Snippets\Livet"

echo project templates
call :copy_project_template_csharp Livet_WPF4.0_CSharp
call :copy_project_template_csharp Livet_WPF4.5_CSharp

call :copy_project_template_vb Livet_WPF4.0_VB
call :copy_project_template_vb Livet_WPF4.5_VB

echo item templates
call :copy_item_template_csharp LivetInteractionMessageAction_CSharp
call :copy_item_template_csharp LivetMessage_CSharp
call :copy_item_template_csharp LivetModel_CSharp
call :copy_item_template_csharp LivetViewModel_CSharp
call :copy_item_template_csharp LivetWindow_CSharp

call :copy_item_template_vb LivetInteractionMessageAction_VB
call :copy_item_template_vb LivetMessage_VB
call :copy_item_template_vb LivetModel_VB
call :copy_item_template_vb LivetViewModel_VB
call :copy_item_template_vb LivetWindow_VB

echo simple install completed!!!
pause

:copy_project_template_csharp
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C#\%1"
exit /b

:copy_project_template_vb
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual Basic\%1"
exit /b

:copy_item_template_csharp
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ItemTemplates\Visual C#\%1"
exit /b

:copy_item_template_vb
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ItemTemplates\Visual Basic\%1"
exit /b
これで見事VS2017に追加されました。めでたしめでたし。