none
ButtonオブジェクトをDragDeltaイベントで移動させたい RRS feed

  • 質問

  • お世話になります。

    表題の通りなのですが、ButtonオブジェクトをDragDeltaイベントを使って移動させたいのです。
    Labelや、TextBlockなどは移動出来ましたが、ButtonやTextBoxは移動が出来ませんでした。
    ButtonやTextBoxなどフォーカスがオブジェクト自体に移ってしまう物は移動が出来ないのでしょうか?
    Buttonを移動させたい場合どうすべきでしょうか?

    宜しくお願い致します。

    <Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Canvas>
            <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" Height="250" Width="250">
                <Thumb.Template>
                    <ControlTemplate>
    
                        <!--ドラッグ対象のオブジェクトを定義する-->
    
                        <!-- 移動OK -->
                        <TextBlock Text="これはTextBlockです。" Width="150" Height="20" Background="Aqua" />
                        <!--<Label Content="これはLabelです。" Width="150" Height="20" Background="Aqua" />-->
    
                        <!-- 移動NG -->                 
                        <!--<Button Content="これはButtonです。" Width="150" Height="20" Background="Aqua" />-->
                        <!--<TextBox Text="これはTextBoxです。" Width="150" Height="20" Background="Aqua" />-->
                        
                        
                        
                    </ControlTemplate>
    
                </Thumb.Template>
            </Thumb>
    
    
        </Canvas>
    </Window>
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    //Thumbコントロールへの参照追加
    using System.Windows.Controls.Primitives;
    
    namespace WpfApplication1
    {
        /// <summary>
        /// Window1.xaml の相互作用ロジック
        /// </summary>
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
    
            //Thumbコントロールのドラッグイベント処理
            private void DragDelta(object sender, DragDeltaEventArgs e)
            {
    
                var thumb = sender as Thumb;
                if (thumb == null) return;
    
                //ドラッグ量に応じてThumbコントロールを移動する
                Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
                Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
            }
        }
    }
    

    2012年9月14日 1:19

回答

  • Preview系のイベントで処理してやるとお手軽にできたり。
    <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" Height="250" Width="250"
            PreviewMouseLeftButtonDown="Thumb_PreviewMouseLeftButtonDown">
        <Thumb.Template>
            <ControlTemplate>
                <!--ドラッグ対象のオブジェクトを定義する-->
                <!-- 移動OK -->
                <!--TextBlock Text="これはTextBlockです。" Width="150" Height="20" Background="Aqua" />-->
                <!--<Label Content="これはLabelです。" Width="150" Height="20" Background="Aqua" />-->
                <!-- 移動NG -->
                <!--<Button Content="これはButtonです。" Width="150" Height="20" Background="Aqua" />-->
                <TextBox Text="これはTextBoxです。" Width="150" Height="20" Background="Aqua" />
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>

    //Thumbコントロールのドラッグイベント処理
    private void DragDelta(object sender, DragDeltaEventArgs e)
    {
        var thumb = sender as Thumb;
        if (thumb == null) return;
        //ドラッグ量に応じてThumbコントロールを移動する
        Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
        Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
    }
    private void Thumb_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Thumb thumb = (Thumb)sender;
        if (Keyboard.PrimaryDevice.Modifiers== ModifierKeys.Alt)
        {
            var mi=typeof(Thumb).GetMethod("OnMouseLeftButtonDown"
                , System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            mi.Invoke(thumb, new object[] { e });
        }
    }

    #私はDrag処理のときはThumb使わずに自前の添付ビヘイビアでやってるので、キーの種類に応じて回転なんかもさせたりしてます。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク sumi_sumi 2012年9月14日 5:09
    2012年9月14日 3:51
  • 少し無理やりな感じがしますが、RoutedEvent を使って実装してみました。一応それっぽい動きになっていると思いますがお試しください。

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Canvas>
            <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" Name="thumb" >
                <Thumb.Template>
                    <ControlTemplate>
                        <Grid Width="180" Height="38" Background="Aqua" Name="grid"
                              Button.PreviewMouseDown="button_MouseDown" 
                              Button.PreviewMouseMove="button_MouseMove" >
                            <Button Content="これはButtonです。" Margin="8" Name="button" />
                        </Grid>
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
        </Canvas>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    
    namespace WpfApplication1 {
        /// <summary>
        /// MainWindow.xaml の相互作用ロジック
        /// </summary>
        public partial class MainWindow : Window {
            public MainWindow() {
                InitializeComponent();
            }
    
            //Thumbコントロールのドラッグイベント処理
            private void DragDelta(object sender, DragDeltaEventArgs e) {
                var thumb = sender as Thumb;
                if (thumb == null) return;
                //ドラッグ量に応じてThumbコントロールを移動する
                Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
                Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
            }
    
            Point _pos;
    
            private void button_MouseDown(object sender, MouseButtonEventArgs e) {
                var button = e.Source as Button;
                if (button != null) {
                    _pos = this.PointToScreen(Mouse.GetPosition(this));
                }
            }
    
            private void button_MouseMove(object sender, MouseEventArgs e) {
                var button = e.Source as Button;
                if (button != null) {
                    if (button.IsPressed) {
                        var pos = this.PointToScreen(Mouse.GetPosition(this));
                        this.thumb.RaiseEvent(new DragDeltaEventArgs(pos.X -_pos.X, pos.Y -_pos.Y));
                        _pos = this.PointToScreen(Mouse.GetPosition(this));
                    }
                }
            }
        }
    }



    ひらぽん http://d.hatena.ne.jp/hilapon/

    • 回答としてマーク sumi_sumi 2012年9月14日 5:09
    2012年9月14日 3:42
    モデレータ

すべての返信

  • > Buttonを移動させたい場合どうすべきでしょうか?

    厄介ですねぇ。代替案としてパネルに Button を配置し、パネルをドラッグすることなら思い浮かぶのですが、この場合パネルは移動できても Button を掴んでの移動はできませんでした。

    <Canvas>
        <ListBox Canvas.Left="21" Canvas.Top="142" Height="154" Name="listBox1" Width="308" />
        <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" >
            <Thumb.Template>
                <ControlTemplate>
                    <Grid Width="180" Height="38" Background="Aqua" >
                        <Button Content="これはButtonです。" Margin="8" />
                    </Grid>
                </ControlTemplate>
            </Thumb.Template>
        </Thumb>
    </Canvas>


    ひらぽん http://d.hatena.ne.jp/hilapon/

    2012年9月14日 3:06
    モデレータ
  • 少し無理やりな感じがしますが、RoutedEvent を使って実装してみました。一応それっぽい動きになっていると思いますがお試しください。

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Canvas>
            <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" Name="thumb" >
                <Thumb.Template>
                    <ControlTemplate>
                        <Grid Width="180" Height="38" Background="Aqua" Name="grid"
                              Button.PreviewMouseDown="button_MouseDown" 
                              Button.PreviewMouseMove="button_MouseMove" >
                            <Button Content="これはButtonです。" Margin="8" Name="button" />
                        </Grid>
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
        </Canvas>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    
    namespace WpfApplication1 {
        /// <summary>
        /// MainWindow.xaml の相互作用ロジック
        /// </summary>
        public partial class MainWindow : Window {
            public MainWindow() {
                InitializeComponent();
            }
    
            //Thumbコントロールのドラッグイベント処理
            private void DragDelta(object sender, DragDeltaEventArgs e) {
                var thumb = sender as Thumb;
                if (thumb == null) return;
                //ドラッグ量に応じてThumbコントロールを移動する
                Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
                Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
            }
    
            Point _pos;
    
            private void button_MouseDown(object sender, MouseButtonEventArgs e) {
                var button = e.Source as Button;
                if (button != null) {
                    _pos = this.PointToScreen(Mouse.GetPosition(this));
                }
            }
    
            private void button_MouseMove(object sender, MouseEventArgs e) {
                var button = e.Source as Button;
                if (button != null) {
                    if (button.IsPressed) {
                        var pos = this.PointToScreen(Mouse.GetPosition(this));
                        this.thumb.RaiseEvent(new DragDeltaEventArgs(pos.X -_pos.X, pos.Y -_pos.Y));
                        _pos = this.PointToScreen(Mouse.GetPosition(this));
                    }
                }
            }
        }
    }



    ひらぽん http://d.hatena.ne.jp/hilapon/

    • 回答としてマーク sumi_sumi 2012年9月14日 5:09
    2012年9月14日 3:42
    モデレータ
  • Preview系のイベントで処理してやるとお手軽にできたり。
    <Thumb DragDelta="DragDelta" Canvas.Left="12" Canvas.Top="12" Height="250" Width="250"
            PreviewMouseLeftButtonDown="Thumb_PreviewMouseLeftButtonDown">
        <Thumb.Template>
            <ControlTemplate>
                <!--ドラッグ対象のオブジェクトを定義する-->
                <!-- 移動OK -->
                <!--TextBlock Text="これはTextBlockです。" Width="150" Height="20" Background="Aqua" />-->
                <!--<Label Content="これはLabelです。" Width="150" Height="20" Background="Aqua" />-->
                <!-- 移動NG -->
                <!--<Button Content="これはButtonです。" Width="150" Height="20" Background="Aqua" />-->
                <TextBox Text="これはTextBoxです。" Width="150" Height="20" Background="Aqua" />
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>

    //Thumbコントロールのドラッグイベント処理
    private void DragDelta(object sender, DragDeltaEventArgs e)
    {
        var thumb = sender as Thumb;
        if (thumb == null) return;
        //ドラッグ量に応じてThumbコントロールを移動する
        Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
        Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
    }
    private void Thumb_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Thumb thumb = (Thumb)sender;
        if (Keyboard.PrimaryDevice.Modifiers== ModifierKeys.Alt)
        {
            var mi=typeof(Thumb).GetMethod("OnMouseLeftButtonDown"
                , System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            mi.Invoke(thumb, new object[] { e });
        }
    }

    #私はDrag処理のときはThumb使わずに自前の添付ビヘイビアでやってるので、キーの種類に応じて回転なんかもさせたりしてます。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク sumi_sumi 2012年9月14日 5:09
    2012年9月14日 3:51
  • ひらぽんさま

    有難う御座います。

    RoutedEventを使うやり方参考になりました。

    まだ解読出来ておりませんが、動きだけ確認させていただきました。

    有難う御座います。

    2012年9月14日 5:11
  • gekkaさま

    有難う御座います。

    これだけのコードで実現出来るとは・・・・。

    驚愕です(*_*;)/

    しかも他のキーと合わせる機能など目からウロコです。

    じっくり参考にさせていただきます。

    大変勉強になります。

    有難う御座います。

    2012年9月14日 5:13