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 を変更するほうが、手早いのかも。試してみます。