locked
マウスでつかんでドラッグする。 RRS feed

  • 質問

  •  Visual Studio 2010 professional にて Silverlight Application を触って試しているところです。VS では 2003 にて C# による業務用 Web Applicaiton を開発運營しておりました。Silverlight をあれこれと調べてみした。TextBlock をマウスでつかんで画面上を引きずりまわしたりすることは簡単にできるようです。特に、マウスイベントに対して十分な Event Handler が用意されている点に可能性を感じます。そこで CANVAS 全体をつかんで引きずりまわしたり、、、というのはどうでしょうか。ご多分に漏れず Google Map の動きがやってみたいと思っております。

     Canvas 上に TextBlock などの Web パーツをいくつか入れておいて、マウスでつかんでドラッグする、というのは、どういう具合にすればできるでしょうか。

    2010年8月3日 9:43

回答

  • 試しに実装してみました。参考にどうぞ。

    <UserControl x:Class="DragDropSample.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">
      <Canvas x:Name="LayoutRoot"
          Background="White">
        <Canvas Canvas.Top="50"
            Canvas.Left="50"
            MouseLeftButtonDown="_canvas_MouseLeftButtonDown"
            MouseMove="_canvas_MouseMove"
            MouseLeftButtonUp="_canvas_MouseLeftButtonUp"
            Background="Blue"
            Width="300"
            Height="300">
          <TextBox Canvas.Top="10"
               Canvas.Left="10"/>
        </Canvas>
      </Canvas>
    </UserControl>
    
    
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace DragDropSample
    {
      public partial class MainPage : UserControl
      {
        public MainPage()
        {
          InitializeComponent();
        }
        
        bool isMouseCaptured;
        double mouseVerticalPosition;
        double mouseHorizontalPosition;
    
        private void _canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
          Canvas panel = sender as Canvas;
          mouseVerticalPosition = e.GetPosition(null).Y;
          mouseHorizontalPosition = e.GetPosition(null).X;
          isMouseCaptured = true;
          panel.CaptureMouse();
        }
    
        private void _canvas_MouseMove(object sender, MouseEventArgs e)
        {
          Canvas panel = sender as Canvas;
          if (isMouseCaptured)
          {
            // 現在の位置を計算
            double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
            double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
            double newTop = deltaV + (double)panel.GetValue(Canvas.TopProperty);
            double newLeft = deltaH + (double)panel.GetValue(Canvas.LeftProperty);
    
            // 新しい位置を設定
            panel.SetValue(Canvas.TopProperty, newTop);
            panel.SetValue(Canvas.LeftProperty, newLeft);
    
            // ポジションを保存
            mouseVerticalPosition = e.GetPosition(null).Y;
            mouseHorizontalPosition = e.GetPosition(null).X;
          }
        }
    
        private void _canvas_MouseLeftButtonUp(object panel, MouseButtonEventArgs e)
        {
          Canvas item = panel as Canvas;
          isMouseCaptured = false;
          item.ReleaseMouseCapture();
          mouseVerticalPosition = -1;
          mouseHorizontalPosition = -1;
        }
      }
    }
    
    


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答の候補に設定 山本春海 2010年8月9日 8:41
    • 回答としてマーク 山本春海 2010年8月18日 5:07
    2010年8月3日 11:30
  • Canvas も TextBlock と同じ方法で、ドラッグ&ドロップで移動できます。下記ページで紹介されている方法をCanvasに応用すればいいです。

    http://msdn.microsoft.com/ja-jp/library/cc189066(VS.95).aspx

    ただし、動かしたいCanvasを、別のCanvasの中に置いておく必要があります。


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答の候補に設定 山本春海 2010年8月9日 8:41
    • 回答としてマーク 山本春海 2010年8月18日 5:07
    2010年8月3日 10:28

すべての返信

  • Canvas も TextBlock と同じ方法で、ドラッグ&ドロップで移動できます。下記ページで紹介されている方法をCanvasに応用すればいいです。

    http://msdn.microsoft.com/ja-jp/library/cc189066(VS.95).aspx

    ただし、動かしたいCanvasを、別のCanvasの中に置いておく必要があります。


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答の候補に設定 山本春海 2010年8月9日 8:41
    • 回答としてマーク 山本春海 2010年8月18日 5:07
    2010年8月3日 10:28
  • 試しに実装してみました。参考にどうぞ。

    <UserControl x:Class="DragDropSample.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">
      <Canvas x:Name="LayoutRoot"
          Background="White">
        <Canvas Canvas.Top="50"
            Canvas.Left="50"
            MouseLeftButtonDown="_canvas_MouseLeftButtonDown"
            MouseMove="_canvas_MouseMove"
            MouseLeftButtonUp="_canvas_MouseLeftButtonUp"
            Background="Blue"
            Width="300"
            Height="300">
          <TextBox Canvas.Top="10"
               Canvas.Left="10"/>
        </Canvas>
      </Canvas>
    </UserControl>
    
    
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace DragDropSample
    {
      public partial class MainPage : UserControl
      {
        public MainPage()
        {
          InitializeComponent();
        }
        
        bool isMouseCaptured;
        double mouseVerticalPosition;
        double mouseHorizontalPosition;
    
        private void _canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
          Canvas panel = sender as Canvas;
          mouseVerticalPosition = e.GetPosition(null).Y;
          mouseHorizontalPosition = e.GetPosition(null).X;
          isMouseCaptured = true;
          panel.CaptureMouse();
        }
    
        private void _canvas_MouseMove(object sender, MouseEventArgs e)
        {
          Canvas panel = sender as Canvas;
          if (isMouseCaptured)
          {
            // 現在の位置を計算
            double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
            double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
            double newTop = deltaV + (double)panel.GetValue(Canvas.TopProperty);
            double newLeft = deltaH + (double)panel.GetValue(Canvas.LeftProperty);
    
            // 新しい位置を設定
            panel.SetValue(Canvas.TopProperty, newTop);
            panel.SetValue(Canvas.LeftProperty, newLeft);
    
            // ポジションを保存
            mouseVerticalPosition = e.GetPosition(null).Y;
            mouseHorizontalPosition = e.GetPosition(null).X;
          }
        }
    
        private void _canvas_MouseLeftButtonUp(object panel, MouseButtonEventArgs e)
        {
          Canvas item = panel as Canvas;
          isMouseCaptured = false;
          item.ReleaseMouseCapture();
          mouseVerticalPosition = -1;
          mouseHorizontalPosition = -1;
        }
      }
    }
    
    


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答の候補に設定 山本春海 2010年8月9日 8:41
    • 回答としてマーク 山本春海 2010年8月18日 5:07
    2010年8月3日 11:30
  • ご教示の code で Application を作成して試してみました。すごくいい動きです。ありがとうございました。

    private void _canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
          Canvas panel = sender as Canvas;
          mouseVerticalPosition = e.GetPosition(null).Y;
          mouseHorizontalPosition = e.GetPosition(null).X;
          isMouseCaptured = true;
          panel.CaptureMouse();
        }

    において、
    Canvas panel = sender as Canvas;
    の部分が、自分から見ると敷居の高さを感じる code です。そこで xaml ファイルの中で Canvas に x:Name="ChildCanvas" のように名前を付けておいて
    private void _canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
          mouseVerticalPosition = e.GetPosition(null).Y;
          mouseHorizontalPosition = e.GetPosition(null).X;
          isMouseCaptured = true;
          ChildCanvas.CaptureMouse();
        }
    のように書いても同じ結果になるということでよろしいのでしょうか。

    2010年8月3日 22:42
  • XAML上でコントロールに名前を付けたくなかったからそうしているだけです。

    x:Name で名前を付けておいて、それを使っても同じ動作になると思います。


    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年8月4日 2:37