トップ回答者
WPFで、○の画像の上に数字や文字を入れて、1列に並べたい

質問
-
いつもお世話になります。
VisualC#2010、WindowsXPでの動作について質問があります。
WPFで、○の画像の上に数字や文字を入れて、1列に並べたいと思っています。
重ねるのにCanvasを使い、並べるのにStackPanelを使ってみました。
(A)(B)(C)
みたいにです。StackPanel horizontalpanel = new StackPane();
horizontalpanel.Orientation = Orientation.Horizontal;
BitmapImage circleBmp = new BitmapImage(circleFileName);
Image circleImage = new Image();
circleImage.Source = circleBmp;string[] words = {"A","B","C"};
foreach(string word in words) {
TextBlock textblock = new TextBlock();
textblock.Text = word;
Canvas canvas = new Canvas();
canvas.Children.Add(textblock);
canvas.Children.Add(circleImage);
horizontalpanel.Children.Add(canvas);
}で、これを実行すると、変に重なってしまいます。
どのようにしたらよいか、アドバイスお願いします。
回答
-
Canvas の Width/Height を設定しないと、Canvas は自身の横幅を決定できません(Canvas は自身の大きさを決定するときに子要素の配置を考慮しません)。そのため、StackPanel の最後の要素以外は幅 0 でレンダリングされます。
個人的には、この場合なら ItemsControl を使ってバインディングしますね。ItemsPanel を使って横方向への StackPanel にしておき、ItemTemplate で Grid を使って背景と文字を重ねます。
- 回答としてマーク HANA01 2010年9月24日 14:06
-
現象が再現できました。確かに、重なってしまいますね。調べてみたところ、下記のページを見つけました。
http://stackoverflow.com/questions/1205851/problem-adding-canvasses-to-a-stackpanel-in-code-in-wpf
CanvasをStackPanelに追加するとき、WidthやHeightを指定しないと上手く表示されないみたいですね。試しにWidthを指定したら、重ならずに表示されました。
StackPanel horizontalpanel = new StackPanel(); horizontalpanel.Orientation = Orientation.Horizontal; Uri circleFileName = new Uri("画像のURI", UriKind.Relative); BitmapImage circleBmp = new BitmapImage(circleFileName); string[] words = { "A", "B", "C" }; foreach (string word in words) { TextBlock textblock = new TextBlock(); textblock.Text = word; Image circleImage = new Image(); circleImage.Source = circleBmp; Canvas canvas = new Canvas(); // Width を表示したら重ならずに表示される canvas.Width = 300; Canvas.SetLeft(circleImage, 10); Canvas.SetTop(circleImage, 10); Canvas.SetLeft(textblock, 50); Canvas.SetTop(textblock, 50); canvas.Children.Add(circleImage); canvas.Children.Add(textblock); horizontalpanel.Children.Add(canvas); }
なかむら(http://d.hatena.ne.jp/griefworker)- 回答としてマーク HANA01 2010年9月27日 6:33
すべての返信
-
で、これを実行すると、変に重なってしまいます。
どのようにしたらよいか、アドバイスお願いします。
「変に重なってしまう」とは、どういうことでしょうか?画像の上に文字が表示されない、ということですか?
もしそうだとすると、Canvas に追加する順が textblock → circleImage なので、circleImage が textblock の上に配置されてしまっているためだと思います。
circleImage の後に textblock を Canvas に追加すれば、画像の上に文字を表示できるはずです。(試していませんが…)
なかむら(http://d.hatena.ne.jp/griefworker) -
-
Canvas の Width/Height を設定しないと、Canvas は自身の横幅を決定できません(Canvas は自身の大きさを決定するときに子要素の配置を考慮しません)。そのため、StackPanel の最後の要素以外は幅 0 でレンダリングされます。
個人的には、この場合なら ItemsControl を使ってバインディングしますね。ItemsPanel を使って横方向への StackPanel にしておき、ItemTemplate で Grid を使って背景と文字を重ねます。
- 回答としてマーク HANA01 2010年9月24日 14:06
-
現象が再現できました。確かに、重なってしまいますね。調べてみたところ、下記のページを見つけました。
http://stackoverflow.com/questions/1205851/problem-adding-canvasses-to-a-stackpanel-in-code-in-wpf
CanvasをStackPanelに追加するとき、WidthやHeightを指定しないと上手く表示されないみたいですね。試しにWidthを指定したら、重ならずに表示されました。
StackPanel horizontalpanel = new StackPanel(); horizontalpanel.Orientation = Orientation.Horizontal; Uri circleFileName = new Uri("画像のURI", UriKind.Relative); BitmapImage circleBmp = new BitmapImage(circleFileName); string[] words = { "A", "B", "C" }; foreach (string word in words) { TextBlock textblock = new TextBlock(); textblock.Text = word; Image circleImage = new Image(); circleImage.Source = circleBmp; Canvas canvas = new Canvas(); // Width を表示したら重ならずに表示される canvas.Width = 300; Canvas.SetLeft(circleImage, 10); Canvas.SetTop(circleImage, 10); Canvas.SetLeft(textblock, 50); Canvas.SetTop(textblock, 50); canvas.Children.Add(circleImage); canvas.Children.Add(textblock); horizontalpanel.Children.Add(canvas); }
なかむら(http://d.hatena.ne.jp/griefworker)- 回答としてマーク HANA01 2010年9月27日 6:33
-
先日のCanvasで、画像/文字をクリックしたときに、処理をしたいのですが、どのようにイベントハンドラを登録したらよいでしょう?
TextBlock textblock = new TextBlock();
textblock.Text = word;textblock.Click += (s,e) => textblock_Click(s,e);
textblock.PreviewMouseUp += MouseUpHandler;Canvas canvas = new Canvas();
canvas.PreviewMouseUp += MouseUpHandler;
canvas.Children.Add(textblock);
canvas.Children.Add(circleImage);などと、textblockとcanvasにイベントハンドラを登録してみましたが、
textblock.Click += (s,e) => textblock_Click(s,e);
ではClickというイベントがないといわれました。
canvas.PreviewMouseUp += MouseUpHandler;
では、なにも処理されていないように見えます。(A)をクリックしたら、
MessageBoxにAを表示する、というように処理したいです。