WPFやSilverlightの表示は、XAMLで作成されているので、うまくやれば Windows アプリケーションの図形移動よりも楽に移動ができる…ハズです。
Windows コントロールの場合は、ボタンなどのような標準コントロールの場合はドラッグ&ドロップのイベントが用意されているのですが、四角や文字などを移動しようと思うと途端に難しくなります。
# マウスイベントを拾って移動すればいいだけなのですが、まあ、
# 面倒と言えば面倒。図形のサイズを変えようとすると、ひと苦労だし。
WPFやSilverlightのビューは、XAMLで書かれているので、ここの値を直接書き変えてやれば、移動や回転などができます。ボタン以外も、矩形や円なども同様に移動などができるわけです。
で、実際にやってみたのですが、結果を言えば、やっぱり「ひと苦労」ですね。
矩形のハンドル(四隅にある四角)を使って大きさなどを変えようと思うと、ハンドル自身のマウスダウンイベントや、移動のイベントなどを拾う必要があります。
さて、具体的な例は、もう少しソースを整理してから紹介することにして。
実は WPF と Silverlight には、あらかじめドラッグできるコントロールが用意されています。これが、「Thumbコントロール」なのです。リストボックスなどのスクロールバーに使われています。
Thumb クラス
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.primitives.thumb.aspx
で、結論を先に言うと、これを使って汎用的なドラッグできるコントロールができるかというと、「できません!」。あくまで、スクロールバーなどに使うコントロールで、一般的な形になっていません。なので、色やら枠線やらが固定になっています。
ま、ひとつ、参考までにソースを晒しておきます。
■WPFの場合
<Window x:Class="SampleThumb.Window1" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml Title="Window1" Height="300" Width="400"> <Canvas> <TextBlock Canvas.Left="0" Canvas.Top="0" Height="22" Name="textPos" Width="75" Text="x:0 y:0" /> <Rectangle Canvas.Left="46" Canvas.Top="48" Height="70" Name="rectangle1" Stroke="Black" Width="109" Fill="pink"/> <Thumb Canvas.Left="141" Canvas.Top="103" Height="30" Name="mark" Width="30" Background="LightBlue" DragCompleted="mark_DragCompleted" DragStarted="mark_DragStarted" DragDelta="mark_DragDelta" /> </Canvas> </Window>
namespace SampleThumb { /// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void printPos( UIElement el) { int x = (int)Canvas.GetLeft( el ); int y = (int)Canvas.GetTop( el ); textPos.Text = string.Format("x:{0} y:{1}", x, y); } /// <summary> /// ドラッグ開始 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { mark.Background = Brushes.Pink; Debug.Print("start"); } /// <summary> /// ドラッグ終了 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { mark.Background = Brushes.LightBlue; Debug.Print("end"); } /// <summary> /// ドラッグ中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { printPos(mark); Canvas.SetLeft(mark, Canvas.GetLeft(mark) + e.HorizontalChange); Canvas.SetTop(mark, Canvas.GetTop(mark) + e.VerticalChange); } } }
肝は、Thumb コントロールの3つのイベントです。
・DragStartedイベント
・DragCompletedイベント
・DragDeltaイベント
ドラッグ中は、DragDeltaイベント内で、mark(移動するThumbコントロール)の位置を変更します。位置は、canvas を使って簡便に、SetLeft、SetTop メソッドを使っています。
■Silverlightの場合
まったく同じものが Silverlight でも動作します。
<UserControl x:Class="SampleThumbSilverlight.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml xmlns:d="<a href="http://schemas.microsoft.com/expression/blend/2008">http://schemas.microsoft.com/expression/blend/2008</a>" xmlns:mc="<a href="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006</a>" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="300"> <Canvas x:Name="LayoutRoot"> <TextBlock Canvas.Left="0" Canvas.Top="0" Height="22" Name="textPos" Width="75" Text="x:0 y:0" /> <Rectangle Canvas.Left="46" Canvas.Top="48" Height="70" Name="rectangle1" Stroke="Black" Width="109" Fill="pink"/> <Thumb Canvas.Left="141" Canvas.Top="103" Height="30" Name="mark" Width="30" Background="LightBlue" DragCompleted="mark_DragCompleted" DragStarted="mark_DragStarted" DragDelta="mark_DragDelta" /> </Canvas> </UserControl>
namespace SampleThumbSilverlight { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void printPos(UIElement el) { int x = (int)Canvas.GetLeft(el); int y = (int)Canvas.GetTop(el); textPos.Text = string.Format("x:{0} y:{1}", x, y); } /// <summary> /// ドラッグ開始 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { mark.Background = new SolidColorBrush(Colors.Orange); } /// <summary> /// ドラッグ終了 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { mark.Background = new SolidColorBrush(Colors.Purple); } /// <summary> /// ドラッグ中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mark_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { printPos(mark); Canvas.SetLeft(mark, Canvas.GetLeft(mark) + e.HorizontalChange); Canvas.SetTop(mark, Canvas.GetTop(mark) + e.VerticalChange); } } }
Siverlight の動作はこちらで確認できます。
http://www.moonmile.net/sl/SampleThumb/
という訳で、Thumbコントロールは汎用的ではないので「使えない」。
仕方がないので、MouseLeftButtonDown イベントなどを地道に取得することになります。
~~ 2010/04/01 追記 ~~
「使えない」と思っていたのですが、Template 化して使うことができました。
となると、自前でドラッグフラグを作らなくていいから、Thumb コントロールは使えるのでは?
すみません、
>あくまで、スクロールバーなどに使うコントロールで、一般的な形になっていません。なので、色やら枠線やらが固定になっています。
これってどういう意味ですか?
他のコントロール同様、TemplateにEllipseなりTextBoxなり適当に詰め込んでみたら
ちゃんとドラッガブルになりましたが…
Canvasの外に持っていけないって事をおっしゃってます?
おお、なるほど!Templateにするといけますね。これはやっていませんでした。
ありがとうございます。
実は「できない」と思っていたから、矩形の大きさを変えるハンドル(四隅の小さな四角)を自作していたんですよね。あと、矢印を動的に配置するツール。う~ん、これだと、ハンドル部分を Thumb の Template を変更するほうが、手早いのかも。試してみます。