Calender

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< December 2018 >>

Categories

Archives

Recent Entries

Recent Comment

Recent Trackback

w closet×JUGEM

-

勉強中・・・

昨日からヒエラルキーデータで悩んでいる。

というわけで、景気づけに電気グルーヴの「イルボン2000」を聴きながら。

間違えて、iPhoneを初期化してしまい、使えなくなったため、電気グルーヴを一ヶ月ほど封印していた。

 

電気グルーヴ、やばい。図書館なのに、踊り出しそうだわ。

 

  • 2018.08.11 Saturday
  • 15:41

-

c# - (ID/ParentID) list to Hierarchical list - Stack Overflow

https://stackoverflow.com/questions/9409021/id-parentid-list-to-hierarchical-list


iPadから送信
  • 2018.08.11 Saturday
  • 14:22

-

お盆休み初日

午前中は、家族と図書館。

昼は、図書館のランチで、とんかつ定食。ひとりで。

午後は、図書館で引き続き、ひとりで仕事の勉強。

GRADIUS兇硫山擇鯆阿ながら・・・

  • 2018.08.11 Saturday
  • 13:30

-

GitHub - dev4sys/PsTreeFolderBrowser: A TreeView in PowerShell

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } GitHub - dev4sys/PsTreeFolderBrowser: A TreeView in PowerShell

dev4sys/PsTreeFolderBrowser

README.md



iPadから送信
  • 2018.08.11 Saturday
  • 06:56

-

WPF TreeViewを簡単にExplorer風にしたかったのでModelを作ってみた

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } WPF TreeViewを簡単にExplorer風にしたかったのでModelを作ってみた

WPF TreeViewを簡単にExplorer風にしたかったのでModelを作ってみた

過去に何度かTreeViewをいじってExplorer風にしたりしてみたが、汎用的に使えるようにしたかったので改めて作ってみた
このModelを使うと簡単にこんなのが作れる

2017-07-13_10h19_05.jpg

Model

    /// <summary>
    /// ルートディレクトリ用クラス
    /// <para>_RootDirectoryに追加したNodeがルートになる</para>
    /// <para>コンストラクタでは1つのルートだけ追加するか、コレクションで複数のルートを追加できる</para>
    /// </summary>
    public class RootDirectoryNode
    {
        /// <summary>
        /// ルートNodeのリスト
        /// こいつをバインドする
        /// </summary>
        public ObservableCollection<BaseNode> _RootDirectory { get; private set; } = new ObservableCollection<BaseNode>();

        /// <summary>
        /// 1つのルートノードを持たせるコンストラクタ(string)
        /// </summary>
        /// <param name="rootDirectoryPath"></param>
        /// <param name="helper"></param>
        public RootDirectoryNode(string rootDirectoryPath, TreeViewHelper helper)
        {
            _RootDirectory.Add(TryCreateDirectoryNode(rootDirectoryPath, helper));
        }

        /// <summary>
        /// 1つのルートノードを持たせるコンストラクタ(DirectoryInfo)
        /// </summary>
        /// <param name="rootDirectoryPath"></param>
        /// <param name="helper"></param>
        public RootDirectoryNode(DirectoryInfo rootDirectory, TreeViewHelper helper)
        {
            _RootDirectory.Add(new DirectoryNode(rootDirectory, helper));
        }

        /// <summary>
        /// 複数のルートノードを持たせるコンストラクタ(string)
        /// </summary>
        /// <param name="rootDirectoryPathList"></param>
        /// <param name="helper"></param>
        public RootDirectoryNode(IEnumerable<string> rootDirectoryPathList, TreeViewHelper helper)
        {
            CommonSetRootDirectories(rootDirectoryPathList.Select(x => TryCreateDirectoryNode(x, helper)).ToList());
        }

        /// <summary>
        /// 複数のルートノードを持たせるコンストラクタ(DirectoryInfo)
        /// </summary>
        /// <param name="rootDirectoryPathList"></param>
        /// <param name="helper"></param>
        public RootDirectoryNode(IEnumerable<DirectoryInfo> rootDirectoryList, TreeViewHelper helper)
        {
            CommonSetRootDirectories(rootDirectoryList.Select(x => new DirectoryNode(x,helper)).ToList());
        }

        /// <summary>
        /// 1つのルートノードを再度セットする(string)
        /// </summary>
        /// <param name="rootDirectoryPath"></param>
        /// <param name="helper"></param>
        public void SetRootDirectory(string rootDirectoryPath, TreeViewHelper helper)
        {
            CommonSetRootDirectory(TryCreateDirectoryNode(rootDirectoryPath, helper));
        }

        /// <summary>
        /// 1つのルートノードを再度セットする(DirectoryInfo)
        /// </summary>
        /// <param name="rootDirectory"></param>
        /// <param name="helper"></param>
        public void SetRootDirectory(DirectoryInfo rootDirectory,TreeViewHelper helper)
        {
            CommonSetRootDirectory(new DirectoryNode(rootDirectory, helper));
        }

        /// <summary>
        /// 複数のルートノードを再度セットする(string)
        /// </summary>
        /// <param name="rootDirectoryPaths"></param>
        /// <param name="helper"></param>
        public void SetRootDirectories(IEnumerable<string> rootDirectoryPaths, TreeViewHelper helper)
        {
            CommonSetRootDirectories(rootDirectoryPaths.Select(x => TryCreateDirectoryNode(x, helper)).ToList());
        }

        /// <summary>
        /// 複数のルートノードを再度セットする(DirectoryInfo)
        /// </summary>
        /// <param name="rootDirectoryPathList"></param>
        /// <param name="helper"></param>
        public void SetRootDirectories(IEnumerable<DirectoryInfo> rootDirectories, TreeViewHelper helper)
        {
            CommonSetRootDirectories(rootDirectories.Select(x => new DirectoryNode(x, helper)).ToList());
        }

        /// <summary>
        /// ルートノードに指定パスのDirectoryNodeを追加する
        /// </summary>
        /// <param name="rootDirectoryPath"></param>
        /// <param name="helper"></param>
        public void AddRootDirectory(string rootDirectoryPath,TreeViewHelper helper)
        {
            _RootDirectory.Add(TryCreateDirectoryNode(rootDirectoryPath, helper));
        }

        /// <summary>
        /// ルートノードに指定ディレクトリのDirectoryNodeを追加する
        /// </summary>
        /// <param name="rootDirectoryPath"></param>
        /// <param name="helper"></param>
        public void AddRootDirectory(DirectoryInfo rootDirectoryPath, TreeViewHelper helper)
        {
            _RootDirectory.Add(new DirectoryNode(rootDirectoryPath, helper));
        }

        /// <summary>
        /// ルートノードに指定パスのFileNodeを追加する
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="helper"></param>
        public void AddFileNode(string filePath,TreeViewHelper helper)
        {
            _RootDirectory.Add(TryCreateFileNode(filePath, helper));
        }

        /// <summary>
        /// ルートノードに指定ファイルのFileNodeを追加する
        /// </summary>
        /// <param name="file"></param>
        /// <param name="helper"></param>
        public void AddFileNode(FileInfo file,TreeViewHelper helper)
        {
            _RootDirectory.Add(new FileNode(file, helper));
        }

        /// <summary>
        /// ルートノードを一旦クリアし、引数のノードを追加する
        /// </summary>
        /// <param name="dirNode"></param>
        private void CommonSetRootDirectory(BaseNode dirNode)
        {
            _RootDirectory.Clear();
            _RootDirectory.Add(dirNode);
        }

        /// <summary>
        /// ルートノードを一旦クリアし、引数のノード全てを追加する
        /// </summary>
        /// <param name="dirNodes"></param>
        private void CommonSetRootDirectories(IEnumerable<BaseNode> dirNodes)
        {
            _RootDirectory.Clear();
            foreach (var dirNode in dirNodes)
            {
                _RootDirectory.Add(dirNode);
            }
        }

        /// <summary>
        /// 指定パスにディレクトリが存在するならDirectoryNodeを返す
        /// <para>存在しなければBaseNodeを返す</para>
        /// </summary>
        /// <param name="path"></param>
        /// <param name="helper"></param>
        /// <returns></returns>
        private BaseNode TryCreateDirectoryNode(string path, TreeViewHelper helper)
        {
            if (Directory.Exists(path))
            {
                return new DirectoryNode(new DirectoryInfo(path), helper);
            }
            else
            {
                return new BaseNode() { Header = "フォルダが見つかりません" };
            }
        }

        /// <summary>
        /// 指定パスにファイルが存在するならDirectoryNodeを返す
        /// <para>存在しなければBaseNodeを返す</para>
        /// </summary>
        /// <param name="path"></param>
        /// <param name="helper"></param>
        /// <returns></returns>
        private BaseNode TryCreateFileNode(string path, TreeViewHelper helper)
        {
            if (File.Exists(path))
            {
                return new FileNode(new FileInfo(path), helper);
            }
            else
            {
                return new BaseNode() { Header = "ファイルが見つかりません" };
            }
        }
    }

    /// <summary>
    /// 各情報を参照型として共有するためのヘルパークラス
    /// </summary>
    public class TreeViewHelper
    {
        /// <summary>
        /// ファイル検索時のフィルター
        /// </summary>
        public string _SearchPattern { get; set; } = "*";
        /// <summary>
        /// Headerに表示するアイコンの幅
        /// </summary>
        public double _ImageWidth { get; set; } = 18;
        /// <summary>
        /// Headerに表示するアイコンの高さ
        /// </summary>
        public double _ImageHeight { get; set; } = 15;
        /// <summary>
        /// フォルダ未展開時にHeaderに表示するアイコン
        /// </summary>
        public ImageSource _CloseFolderIcon { get; set; } = new BitmapImage();
        /// <summary>
        /// フォルダ展開時にHeaderに表示するアイコン
        /// </summary>
        public ImageSource _OpenFolderIcon { get; set; } = new BitmapImage();
        /// <summary>
        /// ファイルのHeaderに表示するアイコン
        /// </summary>
        public ImageSource _FileIcon { get; set; } = new BitmapImage();

        public TreeViewHelper(ImageSource closeFolderIcon, ImageSource openFolderIcon, ImageSource fileIcon, string searchPattern = "*", double imageWidth = 18, double imageHeight = 15)
        {
            _SearchPattern = searchPattern;
            _ImageWidth = imageWidth;
            _ImageHeight = imageHeight;
            _CloseFolderIcon = closeFolderIcon;
            _OpenFolderIcon = openFolderIcon;
            _FileIcon = fileIcon;
        }
    }

    /// <summary>
    /// TreeViewItemを継承し、Nodeのベースとなるクラス
    /// </summary>
    public class BaseNode : TreeViewItem
    {
        /// <summary>
        /// 自身が持つFileSystemInfo(DirectoryInfoかFileInfo)
        /// </summary>
        public FileSystemInfo _Info { get; set; }
        /// <summary>
        /// Headerに表示するアイコン
        /// </summary>
        public Image _HeaderImage { get; private set; } = new Image();
        /// <summary>
        /// Headerに表示するテキスト
        /// </summary>
        public TextBlock _HeaderText { get; private set; } = new TextBlock();
        /// <summary>
        /// Headerに表示するアイコンとテキストを持つパネル
        /// </summary>
        public StackPanel _HeaderPanel { get; private set; } = new StackPanel() { Orientation = Orientation.Horizontal };
        public BaseNode()
        {
            _HeaderPanel.Children.Add(_HeaderImage);
            _HeaderPanel.Children.Add(_HeaderText);
            this.Header = _HeaderPanel;

            //これを設定しとかないとバインドエラーが出る
            this.HorizontalContentAlignment = HorizontalAlignment.Left;
            this.VerticalContentAlignment = VerticalAlignment.Center;
        }
    }

    /// <summary>
    /// Directory用のNode
    /// </summary>
    public class DirectoryNode : BaseNode
    {
        /// <summary>
        /// 共有のためのTreeViewHelper
        /// </summary>
        public TreeViewHelper Helper;
        /// <summary>
        /// 1度でも展開したかどうか
        /// </summary>
        private bool hasExpandedOnce = false;

        /// <summary>
        /// 自身のDirectory内にサブDirectoryか_SearchPatternに一致するファイルがあれば、
        /// 展開できることを表示するためにダミーノードを追加する
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="helper"></param>
        public DirectoryNode(DirectoryInfo dir, TreeViewHelper helper)
        {
            this._Info = dir;
            this.Helper = helper;
            this._HeaderImage.Source = Helper._CloseFolderIcon;
            this._HeaderImage.Width = Helper._ImageWidth;
            this._HeaderImage.Height = Helper._ImageHeight;
            this._HeaderText.Text = dir.Name;

            if (dir.Exists)
            {
                try
                {
                    if (dir.EnumerateDirectories().Any() || dir.EnumerateFiles(Helper._SearchPattern).Any())
                    {
                        this.Items.Add(new BaseNode());//ダミーノードの追加
                    }
                }
                //アクセス拒否、ディレクトリ・ファイルが見つからないエラーをスキップ
                catch (Exception e) when (e is UnauthorizedAccessException || e is DirectoryNotFoundException || e is FileNotFoundException)
                {
                    Console.WriteLine(e.Source + ":" + e.Message);
                }
            }
            this.Expanded += DirNode_Expanded;
            this.Collapsed += DirNode_Collapsed;
        }

        /// <summary>
        /// 展開した時、子ノードがあれば_HeaderImageを_OpenFolderIconに変更する
        /// また、はじめて展開した時ならサブDirectoryとFileを探査して子ノードに追加する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DirNode_Expanded(object sender, RoutedEventArgs e)
        {
            var directory = (DirectoryInfo)this._Info;

            if (this.Items.Count > 0)
            {
                this._HeaderImage.Source = this.Helper._OpenFolderIcon;
                if (!hasExpandedOnce)
                {
                    this.Items.Clear();
                    foreach (var dir in directory.GetDirectories())
                    {
                        this.Items.Add(new DirectoryNode(dir, Helper));
                    }
                    foreach (var file in directory.GetFiles(Helper._SearchPattern))
                    {
                        this.Items.Add(new FileNode(file, Helper));
                    }
                    hasExpandedOnce = true;
                }
            }
        }

        /// <summary>
        /// 展開を閉じた時、_HeaderImageを_CloseFolderIconに変更する
        /// このイベントは親Nodeまで伝播するのでIsExpandedプロパティで判定する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DirNode_Collapsed(object sender, RoutedEventArgs e)
        {
            if (!this.IsExpanded) this._HeaderImage.Source = this.Helper._CloseFolderIcon;
        }
    }

    /// <summary>
    /// File用のNode
    /// </summary>
    public class FileNode : BaseNode
    {
        public FileNode(FileInfo file, TreeViewHelper helper)
        {
            this._Info = file;
            this._HeaderImage.Source = helper._FileIcon;
            this._HeaderImage.Width = helper._ImageWidth;
            this._HeaderImage.Height = helper._ImageHeight;
            this._HeaderText.Text = file.Name;
        }
    }

  • 2018.08.11 Saturday
  • 06:55

-

TVアニメ「深夜!天才バカボン」公式サイト

https://shinya-bakabon.com/


iPadから送信
  • 2018.08.11 Saturday
  • 06:54

-

Re[9]: WPFのtreeviewとexpandedイベント

http://bbs.wankuma.com/index.cgi?mode=al2&namber=34832&KLOG=60


iPadから送信
  • 2018.08.11 Saturday
  • 06:52

-

Re[3]: WPFのTreeViewで任意の項目を展開する

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } Re[3]: WPFのTreeViewで任意の項目を展開する

C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

VC#2008 WPFアプリケーション

<TreeView Name="treeView">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type c:MyItem}" ItemsSource="{Binding SubItems}">
            <StackPanel Orientation="Horizontal">
                <Rectangle Width="16" Height="16" Fill="Blue" />
                <Label Content="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>


class MyItem
{
    public string Name { get; set; }
    public List<MyItem> SubItems { get; private set; }

    public MyItem(string name)
    {
        this.Name = name;
        this.SubItems = new List<MyItem>();
    }
}


MyItem item1 = new MyItem("あああ");
MyItem item2 = new MyItem("いいい");
MyItem item3 = new MyItem("ううう");
MyItem item4 = new MyItem("えええ");

item1.SubItems.Add(item2);
item1.SubItems.Add(item3);
item3.SubItems.Add(item4);
this.treeView.ItemsSource = Enumerable.Repeat(item1, 1);


ツリービューの項目を展開する場合はTreeViewItem.IsExpandedをtrueにすればいいようですが
上記のように項目がTreeViewItemで無い場合はIsExpandedが使えません。
例えばitem3の項目を展開したい場合はどうすればいいのでしょうか。


iPadから送信
  • 2018.08.11 Saturday
  • 04:59

-

WPFやXamarinのICommandを改めて整理する - nuits.jp blog

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } WPFやXamarinのICommandを改めて整理する - nuits.jp blog

WPFやXamarinのICommandを改めて整理する

2016.07.10 改定 XamarinにRelayCommand的なデフォルト実装がある事を @qwerty2501 に教えていただき修正しました。
ありがとうございました。

先日(7月7日 木曜日)エクセルソフトさんのビジネスセミナーに行ってきました。

その数日前に
田淵さん:「RelayCommand(DelegateCommandでも可)良く分からない。木曜日に教えて!」
私   :「いいよいいよ、教えるよ」
てな会話をしたのに、セミナー終わったらそのままほったらかして帰ってきてしまったので(ちょっと家庭の事象でw)、その償いに?エントリーとして整理してみることにしました。

なおタイトルにはWPFとXamarinとありますが、UWPとかでも基本は同じだと思います。

と思って書いたんですけど、実は私、みちゃったんですよね。

@amay077 さんに public Command(Action execute, Func<bool> canExecute); を教えていただいた!!!!!Tポイント!!!

— 田淵 義人@エクセルソフト (@ytabuchi)

(´・ω・`)

まぁ書いちゃったから公開するよ。。。

  • ICommandとはなにか
  • ICommandの概要
    • void Execute(object parameter)
    • bool CanExecute(object parameter)
    • event EventHandler CanExecuteChanged;
  • RelayCommand・DelegateCommandとはなにか
  • DelegateCommandの簡単な利用方法

Sponsored Link

ICommandとはなにか

XAMLで発生した何らかの操作に基づき、処理を実行する「コマンド」を表します。
例えば、ButtonのCommandプロパティにICommandの実態をバインドすることで、ボタンをクリックされた際に処理を実行する事が出来ます。
メソッドと何が違うの?というと、以下の点が異なります。

  1. 処理の実行可否を状態として持つ事ができ、また状態の変更を通知できる
  2. 標準の仕組みではXAMLからメソッドの呼び出しはXAMLと同一クラス内のメソッド(コードビハインド)しか利用できないが、ICommandであればバインドが利用できる=別クラス(主にViewModel)の処理を呼び出すことができる

といった特徴があります。
この為、XAMLアーキテクチャで開発する上で、最も重要で基本的な概念の一つと言っても、まぁ誰も怒りはしないと思います。

ICommandの概要

さて、それではICommandをもう少し掘り下げてみてみましょう。

    public interface ICommand
    {
        void Execute(object parameter);
        bool CanExecute(object parameter);
        event EventHandler CanExecuteChanged;
    }

ICommandには3つのメンバが存在します。
順番に説明していきます。

void Execute(object parameter)

コマンドで実行する処理の実体です。
parameterにはXAML側でCommandParameterというのを指定すると渡されてきます。
ただ、これはあくまで私個人の考えですが、ちゃんと必要な値がViewModelにバインドされていれば、どうしてもparameterで渡したいというケースはあまり多くなく、利用頻度は低いです。
CommandParameterがXAML側で指定されていないと、nullが渡ってきます。

bool CanExecute(object parameter)

コマンドが実行可能な状態かどうか判定します。 例えばコマンドがButtonのCommandプロパティにバインドされていた場合、この戻り値がfalseを返却すると、Buttonが非活性状態となります。 parameterには以下略

event EventHandler CanExecuteChanged;

コマンドの状態が変更されたことに伴い、CanExecuteの返す値が変わった場合、このイベントで変更があったことを通知します。
イベントを受信した側は、改めてCanExecuteを実行し、状態の変更に対応します。

例えば、入力フォームがあって、登録ボタンがあったとします。
その際に、氏名が必須だった場合に、氏名が入力されていたら登録ボタンを有効化するといったことを、容易に実現することが可能になるわけです。
慣れると便利ですよ!

RelayCommand・DelegateCommandとはなにか

さて、ここからが本題といえば本題です。
ICommand、非常に便利かつ強力な仕組みなのですが、WPFでもXamarinでも標準では実装が存在しません。
かといって、毎度用途に合わせて実装するのも大変です。

2016.07.10 改定 XamarinにはXamarin.Forms.Commandクラスという同様のデフォルト実装がありましたので、他のMVVMフレームワークを使わない場合はこちらを利用するとよいと思います。

そこでRelayCommandまたはDelegateCommandの登場です。
名前は異なりますが、実際にはほぼ同じものです。
私が見た範囲では当初MSの文献にはRelayCommandという名称で出ていましたが、現在のPrismなどのMVVMフレームワークではDelegateCommandという名称で提供されています。
まあ、本エントリー内ではDelegateCommandという名称で以後は統一しようと思います。

ではDelegateCommandとは何者か?端的に言うと
「コマンドの実行処理をActionとして、実行可否の判定をboolを返却するFuncを渡すことでインスタンス化できるICommand」
です。

通常はPrismとかMVVMLightとかLivetとか、何らかのMVVMフレームワークを使うと思いますが、どのフレームワークでも類する実装が含まれています。
なかなか、口頭では伝えにくいものがありますので、ここからは実際の使い方を見てもらいましょう。

DelegateCommandの簡単な利用方法

では、実際のDelegateCommandの利用方法を見ていきましょう。
作るものは簡単です。

  • 氏名と住所がある登録フォーム
  • 氏名が必須入力で、氏名が入力されないと登録ボタンは押せない

というだけの、しょぼいアプリになります。
実際の動作イメージは以下の通りです。

WPFやXamarinのICommandを改めて整理する

なお、今回のサンプルではPrismのDelegateCommandの実装を利用します。
WPFで試される場合はNuGetから「Pris.WPF」を検索して追加してください。

まずXAMLです。

<Window x:Class="CommandSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CommandSample"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<StackPanel Orientation="Vertical">
<Label Content="氏名"/>
<TextBox Text="{Binding Name}"/>
<Label Content="住所"/>
<TextBox/>
<Button Content="実行" Command="{Binding ExecuteCommand}"/>
<Label Content="{Binding Result}"/>
</StackPanel>
</Window>

氏名・住所のテキストボックスがあって、その下に登録ボタンがあります。
登録ボタンの下には、登録結果を表示するラベルがあります。

よく見ると以下にバインディングが設定されているのが見て取れると思います。

  • 氏名TextBoxのTextプロパティ
  • 登録ButtonのCommandプロパティ
  • 結果LabelのContentプロパティ

ポイントは登録ButtonのCommandプロパティにバインドされているコマンドです。
なお、住所テキストボックスは「在るだけ」ですが、氏名TextBoxからフォーカスアウトしないと、入力値がVMに渡らない為、一身上の都合で無駄に存在しています。

ではViewModelの方を見てみましょう。
全部見ると大きいので、順番に。以下がポイントのDelegateCommandの部分です。

public DelegateCommand ExecuteCommand { get; }
public MainWindowViewModel()
{
ExecuteCommand =
new DelegateCommand(
() => Result = "登録されました",
CanExecute);
}
private bool CanExecute()
{
return !string.IsNullOrWhiteSpace(Name);
}

DelegateCommandをプロパティとして公開し、コンストラクタの中でインスタンス化しています。

引数は二つあります。

一番目の引数はコマンドのExecuteメソッドを呼ばれた場合に呼び出されるActionです。
実際に実行したい処理の内容を記述します。
ここでは、結果ラベルにメッセージを表示しているだけですね。

二番目の引数はコマンドのCanExecuteに該当するFuncを渡します。
ここではコマンドが実行可能な状態かどうかをboolで返してあげます。
ここではメソッドを渡していますが、もちろんラムダ式で記述しても問題ありません。

二番目の引数は省略することも可能で、省略した場合、常に実行可能な状態となります。

ViewModelでもう一つ重要な点が以下です。

private string _name;
public string Name
{
get { return _name; }
set
{
if (OnPropertyChanged(ref _name, value))
ExecuteCommand.RaiseCanExecuteChanged();
}
}

氏名のTextBoxにバインディングしているプロパティです。
Nameプロパティが変更された場合に、先ほどのExecuteCommandに対して、RaiseCanExecuteChangedメソッドを呼び出すことによって、コマンドの実行可能状態が変わったことを通知してあげます。
すると、対象のコマンドをバインドしているコントロールが、改めてコマンドのCanExecuteを呼び、実行可能状態を取得し、結果、Buttonが有効になります。

と言う分けで、今日はここまで。
それではまた!



iPadから送信
  • 2018.08.11 Saturday
  • 04:59

-

WPF の コマンド 引数 を 設定 する 方法 - galife

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } WPF の コマンド 引数 を 設定 する 方法 - galife

WPF の コマンド 引数 を 設定 する 方法

基本は xaml で CommandParameter属性 を指定することで引数を渡せます。 以下ではいくつかの サンプルコード を記載しました。

目次

  • 固定値 を 渡す 例
  • 要素 を 渡す 例
    • コントロールを渡す例
    • Windowを渡す例
  • 要素 の プロパティ を 渡す 例

固定値 を 渡す 例

CommandParameter="固定値" を指定します。 ラジオボタンくらいしか使い道が思いつきません…。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<Window x:Class="WpfApplication.MainView"

        xmlns:vm="clr-namespace:WpfApplication.ViewModels"

        Title="MainWindow"

        Name="window" >

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <RadioButton Content="春"

                     Command="SelectSeason"

                     CommandParameter="1" />

        <RadioButton Content="夏"

                     Command="SelectSeason"

                     CommandParameter="2" />

        <RadioButton Content="秋"

                     Command="SelectSeason"

                     CommandParameter="3" />

        <RadioButton Content="冬"

                     Command="SelectSeason"

                     CommandParameter="4" />

    </Grid>

</Window>

要素 を 渡す 例

渡したい要素に Name属性 を設定し、CommandParameter="{Binding ElementName=要素名}" を指定します。 Name属性 さえ指定していれば良いので、 Control でも Window でも渡せてしまいます。

TextBox コントロール を引数に渡す 例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<Window x:Class="WpfApplication.MainView"

        xmlns:vm="clr-namespace:WpfApplication.ViewModels"

        Title="MainWindow"

        Name="window" >

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <TextBox Text="サンプル"

                 Name="textbox" />

        <Button Content="閉じる"

                Command="Close"

                CommandParameter="{Binding ElementName=textbox}"/>

    </Grid>

</Window>

Window を引数に渡す 例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<Window x:Class="WpfApplication.MainView"

        xmlns:vm="clr-namespace:WpfApplication.ViewModels"

        Title="MainWindow"

        Name="window" >

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <TextBox Text="サンプル"

                 Name="textbox" />

        <Button Content="閉じる"

                Command="Close"

                CommandParameter="{Binding ElementName=window}"/>

    </Grid>

</Window>

要素 の プロパティ を 渡す 例

渡したい要素に Name属性 を設定し、CommandParameter="{Binding ElementName=要素名 Path=プロパティ名}" を指定します。

TextBox の Textプロパティ を引数に渡す 例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<Window x:Class="WpfApplication.MainView"

        xmlns:vm="clr-namespace:WpfApplication.ViewModels"

        Title="MainWindow"

        Name="window" >

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <TextBox Text="サンプル"

                 Name="textbox" />

        <Button Content="閉じる"

                Command="Close"

                CommandParameter="{Binding ElementName=textbox Path=Text}"/>

    </Grid>

</Window>

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!



iPadから送信
  • 2018.08.11 Saturday
  • 04:59