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

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

C# と VB.NET の入門サイト

Re[4]: プロパティの値をユーザーコントロールの外観に反映する


(過去ログ 133 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■78504 / inTopicNo.1)  プロパティの値をユーザーコントロールの外観に反映する
  
□投稿者/ かさなか (1回)-(2016/01/20(Wed) 13:14:18)

分類:[C#] 

Visual Studio Communityを使っています。c#とWPFで以下のようなユーザーコントロールを作ろうと思っています。
・カスタム依存関係プロパティRows,Columns,CellWidth,CellHeightを元に、任意の行・列・幅・高さを持つマス目を作成する
・プロパティが変更されるとマス目も逐一更新される
プロパティの値と外観を連動させる方法というと、自分にはバインディングしか思いつかず、
結果、XAML側にはContentPresenterを置いてContentプロパティに上記4つのプロパティをMultiBindingし、
コード側でMultiValueConverterを定義して「各プロパティ値に応じたBorderコントロールをGridでラッピングしたもの」に変換するという実装になりました。
ですが、もっと一般的な方法はないのでしょうか?
これ以外にも、プロパティの値に応じて不特定個数のコントロールを表示するようなユーザーコントロールを作成しようとするとこの方法しかできないのですが、どうしても他にもっと適当な実装方法がありそうな気がして手が止まってしまいます。
どなたかご教授ください。
引用返信 編集キー/
■78506 / inTopicNo.2)  Re[1]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ ぶなっぷ (69回)-(2016/01/21(Thu) 10:18:30)
今回の場合、XAMLでやるより、コードでやった方が楽かもしれません。

以下のように、XAMLは Gridの定義だけにします。

  <Grid x:Name="MainGrid" />

で、コード側で以下のようにして、Grid内にRectangleを追加していきます。
分かり易いようにわざとループ使用してないですし、
外枠だけマス目の罫線が細かったりするのも放置してます。
そのあたりは摘便ご修正ください。

MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(30) });
MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(30) });
MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(30) });

MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(30) });
MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(30) });

var Rectangle11 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle11);
Rectangle11.SetValue(Grid.RowProperty, 0);
Rectangle11.SetValue(Grid.ColumnProperty, 0);

var Rectangle12 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle12);
Rectangle12.SetValue(Grid.RowProperty, 0);
Rectangle12.SetValue(Grid.ColumnProperty, 1);

var Rectangle13 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle13);
Rectangle13.SetValue(Grid.RowProperty, 0);
Rectangle13.SetValue(Grid.ColumnProperty, 2);

var Rectangle21 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle21);
Rectangle21.SetValue(Grid.RowProperty, 1);
Rectangle21.SetValue(Grid.ColumnProperty, 0);

var Rectangle22 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle22);
Rectangle22.SetValue(Grid.RowProperty, 1);
Rectangle22.SetValue(Grid.ColumnProperty, 1);

var Rectangle23 = new Rectangle() { Width = 30, Height = 30, Stroke = Brushes.Black };
MainGrid.Children.Add(Rectangle23);
Rectangle23.SetValue(Grid.RowProperty, 1);
Rectangle23.SetValue(Grid.ColumnProperty, 2);

以上です。

引用返信 編集キー/
■78507 / inTopicNo.3)  Re[2]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ ぶなっぷ (70回)-(2016/01/21(Thu) 10:57:21)
伝わっているかと思いますが、一応、

コード中、
  GridLength(30)
  Width = 30, Height = 30
の 30 の部分を、DataContext に指定したクラスのプロパティにすれば、
「プロパティの値をユーザーコントロールの外観に反映する」
という話になります。

引用返信 編集キー/
■78516 / inTopicNo.4)  Re[2]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ かさなか (2回)-(2016/01/21(Thu) 20:55:54)
No78506 (ぶなっぷ さん) に返信
> で、コード側で以下のようにして、Grid内にRectangleを追加していきます。
> 分かり易いようにわざとループ使用してないですし、
> 外枠だけマス目の罫線が細かったりするのも放置してます。
> そのあたりは摘便ご修正ください。

コードのどの部分に記述すれば良いのでしょうか?
コンストラクタ(InitializeComponentの下)に記述すると、ユーザーコントロールの利用側でプロパティに値を代入するよりも先に実行されてしまい、自身のプロパティを指定しても初期値が参照されてしまいます。
Loadedイベントハンドラの中に記述すれば表示時には期待通りに作成できるのですが、動的にプロパティの値を変えても当然更新されず、プロパティ変更時にも同様の処理をしようと方法を探したのですが、依存関係プロパティのコールバックではstaticでない他のプロパティを参照できないため実現できず、RowsやColumnsにはバインディングで値を設定するのでSetterの中でメソッドを呼び出しても反応してくれませんでした。
引用返信 編集キー/
■78518 / inTopicNo.5)  Re[3]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ Hongliang (400回)-(2016/01/21(Thu) 22:45:06)
> 依存関係プロパティのコールバックではstaticでない他のプロパティを参照できないため実現できず
ん?
delegate void DependencyPropertyChangedCallback(DependencyObject, DependencyPropertyChangedEventArgs)
の第1引数DependencyObjectは、その依存関係プロパティの所有者ですからキャストできますよ?
引用返信 編集キー/
■78527 / inTopicNo.6)  Re[4]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ ぶなっぷ (71回)-(2016/01/22(Fri) 10:07:42)
実際に作って試してみました。

以下のようなメソッドを作成して、
外部から呼んであげるとうまくいきました。

ColCount, RowCount, Width, Height の値が変わった後、
再描画したいタイミングで呼んで上げればよさげ。

private void RefreshGrid(int ColCount, int RowCount, int Width, int Height)
{
    MainGrid.Children.Clear();
    MainGrid.ColumnDefinitions.Clear();
    MainGrid.RowDefinitions.Clear();

    for (int ColIdx = 0; ColIdx < ColCount; ColIdx++)
    {
        MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(Width) });
    }
    for (int RowIdx = 0; RowIdx < RowCount; RowIdx++)
    {
        MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(Height) });
    }

    for (int ColIdx = 0; ColIdx < ColCount; ColIdx++)
    {
        for (int RowIdx = 0; RowIdx < RowCount; RowIdx++)
        {
            var Rectangle = new Rectangle() { Width = Width, Height = Height, Stroke = Brushes.Black };
            MainGrid.Children.Add(Rectangle);
            Rectangle.SetValue(Grid.ColumnProperty, ColIdx);
            Rectangle.SetValue(Grid.RowProperty, RowIdx);
        }
    }
}

引用返信 編集キー/
■78539 / inTopicNo.7)  Re[4]: プロパティの値をユーザーコントロールの外観に反映する
□投稿者/ かさなか (4回)-(2016/01/23(Sat) 15:59:32)
2016/01/23(Sat) 16:05:03 編集(投稿者)
No78518 (Hongliang さん) に返信
>>依存関係プロパティのコールバックではstaticでない他のプロパティを参照できないため実現できず
> ん?
> delegate void DependencyPropertyChangedCallback(DependencyObject, DependencyPropertyChangedEventArgs)
> の第1引数DependencyObjectは、その依存関係プロパティの所有者ですからキャストできますよ?
知りませんでした・・・

private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var bordergrid = (BorderGrid)d;

			Redraw_View(
				bordergrid.maingrid,
				bordergrid.Rows,
				bordergrid.Columns,
				bordergrid.CellWidth
				bordergrid.CellHeight);
		}


		private void maingrid_Loaded(object sender, RoutedEventArgs e)
		{
			Redraw_View(maingrid, Rows, Columns, CellWidth, CellHeight);
		}

		private static void Redraw_View(BorderGrid maingrid, int Rows, int Columns, double CellWidth, double CellHeight)
		{
			//maingridを初期化してからBorderコントロールを配置する処理
		}

このようにすることで、無事期待通りのものを作ることができました。
お返事頂いたぶなっぷ様、Hongliang様、ありがとうございました!

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -