«前の日記(2013年09月04日) 最新 次の日記(2013年09月15日)» 編集

日々をアレコレ


2013年09月11日

自力でカスタムコントロール

UserControlだと生成に時間がかかるようで、ラベルとボタンを含むUserControlと、ContorolTemplateを使ってラベルとボタンを含むControlを2000個ほどをnewして、canvasに置いていくという処理をして、その時間を計測したところ、UserControlだと1000msecちょっとかかっていたけど、ControlTemplateを使うと80msecと1/10ほどという結果が出た。1度生成すればその後は使いまわすようなものなら、UserControlの方が扱いやすいけど、生成と削除を繰り返し、一度に数多く生成するような場合は無いてないってわかったので、ControlTemplateを使ったものにしようと決めた。で、調べてみたらそれをカスタムコントロールと呼ぶらしい。残念ながら、VisualStudio2012 Desktop Expressではメニューからカスタムコントロールを作ることができないので、自分で作ってやることに。

まず、カスタムコントロールのテンプレートの作成。これは、リソースディクショナリとして作成すること。プロジェクト内に新しい項目として「リソースディクショナリ」を追加する。中に以下のような定義をすること。

<ResourceDictionary xmlns:local="clr-namespace:HogeHoge">
<ControlTemplate TargetType={x:Type local:FugaFuga} x:Key="FugaTemp">
    <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
        <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
                <RowDefinition Width="*"/>
                <RowDefinition Width="*"/>
        </Grid.RowDefinitions>
        <Label Name="label" Content="{TemplateBinding MyContent}" Grid.Row="0" Grid.Column="0"/>
        <Button Name="button" Content="{TemplateBinding MyContent}" Grid.Row="1" Grid.Column="0"/>
    </Grid>
</ControlTemplate>
</ResourceDictionary>

この場合、namespaceがHogeHoge内にFugaFugaという名前のクラスを作ってあり、そのクラスに対するテンプレートとして、FugaTempをキーとして設定し、ラベルとボタンが上下に並んだ形となっている。

これに対して、HogeHoge.FugaFugaというコントロールは以下のように記述する。

namespace HogeHoge
{
    public class FugaFuga : Control
    {
        private button;        // テンプレート内のボタンオブジェクト参照用
        private label;          // テンプレート内のラベルオブジェクト参照用

        // 独自の依存プロパティ(Contentに相当)
        public static readonly DependencyProperty MyContentProperty = DependencyProperty.Register("MyContent", typeof(string), typeof(FugaFuga));
        public string MyContent
        {
            get { return (string)GetValue(MyContentProperty); }
            set { SetValue(MyContentProperty, value); }
        }

        public FugaFuga() : base()
        {
            // リソースディクショナリ読込
            ResourceDictionary dict  = Application.LoadComponent(new Uri("PathToResourceDictionaryFileFromAppRoot", UriKind.Related);
            // 自身のテンプレートをリソースディクショナリ内のFugaTemplateという名前のものに設定する
            this.Template = dict["FugaTemplate"] as ControlTemplate;
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            initTemplayte;
        }

        protected void initTemplate()
        {
            if (button == null)
            {
                // テンプレート内のボタンオブジェクトを取得
                button = this.Template.FindName("button", this) as Button;
            }
            if (label == null)
            {
                // テンプレート内のラベルオブジェクトを取得
                label = this.Template.FindName("label", this) as Label;
            }
        }
    }
}

FugaFugaクラスのコンストラクタで、リソースディクショナリを読込、その中にある「FugaTemp」キーにあたるControlTemplateを自身のテンプレートに適用している。実際にテンプレートが適用されると、OnApplyTemplateが呼ばれるので、その中でテンプレート内にある要素を探して読みこむ処理をinitTemplate()で実現している。

Tags: wpf

Windowsで使えるGitクライアント

簡単に調べた感じではWindows向けのGitクライアントって、Git for Windows(旧MSYS Git)、cygwinのgitコマンド、TortoiseGitSourceTreeといったあたりがよく使われてるところなんかな?個人的には、GUI大好きだからcygwinは使う気にならないし、Git for WindowsはGUIもついてるけどあまりイケてないので、TortoiseGitとSourceTreeの2択。詳細な解説はいろんなところが書いているので、個人的に感じる大きな違いをメモ。

これが大きいと思ったのは、リモートへのプッシュするとき、プルなりフェッチなりが必要かどうかが一目でわかること。TortoiseGitだと少なくともデフォルトの状態で使っている僕はその方法を知らない。なので、リモートへプルをするときには、ローカルへのコミット、リモートからのプル、リモートへのプッシュの3アクションが必要。けど、SourceTreedだとコミットするとリモートからプルが必要な変更の数がツールバー上に現れるので、何か変更があればプルしてから、何もなければそのままプッシュということができるので、随分とわかりやすいように思った。

また、どっちがいいかというのは個人的な好みの問題なんだろうけども、コミットのときの必要とされることがちょっと違う。TortoiseGitはシェルを起動したフォルダ以下の変更分を自動でコミットの対象とするのでルートフォルダなどそれ以外のツリーにあるフォルダの変更はコミットできない。それに対して、SourceTreeはリポジトリ全体の監視を常にしているので、変更があったファイルが常に一覧化されているので、いろんな場所の変更をしても問題なくコミットできる。ただし、SourceTreeの場合、コミットの際に対象となるファイルを自分で常に選択する必要があるのに対して、TortoiseGitは管理下にあるファイルに変更があれば自動的にコミット対象として選択してくれるという点では楽なんだとは思う。


«前の日記(2013年09月04日) 最新 次の日記(2013年09月15日)» 編集