ダリアメモ@ブログ

日々思ったことや自分用のメモも含めプログラムの技術を淡々と書いていきます

WPFで便利だなと思ったものまとめ

なんだかんだWPFを触って4ヶ月経ちました。
今回はこれ便利だなと思ったものや手間取って時間を取られたたものをまとめようと思います。

◯ComboBoxのバインディング

やることはComboBoxにあるItemsSourceにコレクション変数を渡すだけ。

・サンプル

List<string> testList = new List<string>{“test”,”test2”};
comboBox.ItemsSource = testList;

これでComboBoxのリストにtest,test2が追加される
バインディングしているのでこのtestListに要素を増やしたり減らしたりすればちゃんとComboBoxにも反映されるようになっています。
これだとstringなのでそのまま表示されるようになりますが、クラスのメンバ変数で表示するようにしたかったら
ComboboxのDisplayMemberPathにメンバ変数名を入れれば反映されるようになります。


◯ObservableCollectionに要素を追加したり削除したりする時にイベントを呼ぶ

ObservableCollectionは要素を追加したり削除したりするときにイベントを呼ぶ事が出来ます。
これを使えば追加したタイミングに別の処理を入れるといった使い方もできます。
最近作ったツールの例だと、追加された要素に対してTypeのGetTypeで型を調べ、
それに応じて追加するUIを変えStackPanelやListBoxに動的生成して追加するといったことをしました。

・サンプル

private void AddRemoveEvent(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    //追加処理
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
    {
    //型取得
        string typeName =e.NewItems[0].GetType().Name;
        var objectType = Type.GetType(typeName );
        //インスタンス生成                
        var objectInstance = Activator.CreateInstance(objectType);
        UserControl control = (UserControl)objectInstance;
        //要素追加
        stackpanel.Children.Add(control);
    }
    //削除処理
    else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
    {
    //最初の要素を消す
        stackpanel.Children.RemoveAt(0)
    }
}


◯画像ファイルを別の場所にコピー

Imageなど表示してる画像ファイルを他のディレクトリにコピーしたい場合、画像ファイルをFile.Copy関数でコピーしようとします。
するとImageクラスSourceプロパティがそのままだとそのファイルがアプリケーション側で占用されていて、コピーや削除などファイルに対しての操作が出来ません。
なので画像の生成方法を変えるようにする必要があります。

・サンプル

//カレントディレクトリにあるtest.pngを元に生成
Uri uri = new Uri("test.png", UriKind.Relative));

//==================駄目な方法=================================================

//Uriをもとにビットマップ生成
BitmapImage bitmap = new BitmapImage(uri);

//生成したBitmapインスタンスをそのまま渡す
image.Source = bitmap;
//===============================================================================


//==================良い方法===================================================

//ビットマップ生成
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = uri;
bitmap.EndInit();
//Imageクラスに別の方法で生成したBitmapのインスタンスを渡す
image.Source = bitmap;
//===============================================================================
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = uri;
bitmap.EndInit();

この4つを使うことによってアプリケーションにファイルを占有されない方法で生成することが出来ます。
他にも方法はありますが今回は自分が使ってるこの方法で(こっちのほうがいいよとかあったら教えてくださると嬉しいです)

◯ファイルやディレクトリ以外のドラッグ&ドロップ

よくドラッグ&ドロップで取得したファイルやディレクトリを使ってやり取りしているのですが、これは別にファイルやディレクトリじゃなくても出来るようです。
最近作ったツールだとStackPanelに表示しているUIのDataContextをDragするデータとして渡して、
ドロップ先でデータをキャストして成功したら挙動を変えるといった使い方をしました。

・サンプル

//ドラッグ側
private void TestDrag(object sender, MouseButtonEventArgs e)
{
      //Imageクラス
      Image img = sender as Image;
      //ImageのDataContext(仮にNameというstringのプロパティを持ったTestクラスとする)をドラッグするデータとして渡す
   DataObject dataObj = new DataObject(typeof(Test), img.DataContext);
      DragDrop.DoDragDrop(img , dataObj, DragDropEffects.All);
}
//ドロップ側
private void TestDrop(object sender, DragEventArgs e)
{
      //受け取ったデータがTestクラスかどうかキャストする
      Test test = e.Data.GetData(typeof(Test)) as Test;
      if(test != null)
      {
     //成功したことを書き込む
          test.Name = "ドラッグ成功";
      }
}

以上です。
また何か便利なものがあったら書きます。