web-dev-qa-db-ja.com

WPFポップアップコントロールをドラッグします

wPFポップアップコントロールは素晴らしいですが、私の意見では多少制限されています。ポップアップを開いたときにポップアップを「ドラッグ」する方法はありますか(WindowsのDragMove()メソッドのように)?

これは大きな問題なく実行できますか、それともポップアップクラスの代わりを自分で作成する必要がありますか?ありがとう

19

これがThumbを使用した簡単な解決策です。

  • XAMLおよびコードビハインドのサブクラスポップアップ
  • 幅/高さを0に設定したThumbを追加します(これはXAMLでも実行できます)
  • ポップアップでMouseDownイベントをリッスンし、Thumbで同じイベントを発生させます
  • DragDeltaのポップアップを移動します

XAML:

<Popup x:Class="PopupTest.DraggablePopup" ...>
    <Canvas x:Name="ContentCanvas">

    </Canvas>
</Popup>

C#:

public partial class DraggablePopup : Popup 
{
    public DraggablePopup()
    {
        var thumb = new Thumb
        {
            Width = 0,
            Height = 0,
        };
        ContentCanvas.Children.Add(thumb);

        MouseDown += (sender, e) =>
        {
            thumb.RaiseEvent(e);
        };

        thumb.DragDelta += (sender, e) =>
        {
            HorizontalOffset += e.HorizontalChange;
            VerticalOffset += e.VerticalChange;
        };
    }
}
15
jacob

PopUp用のDragMoveはありません。ちょっとした回避策ですが、これに追加できる改善点がたくさんあります。

<Popup x:Name="pop" IsOpen="True" Height="200" Placement="AbsolutePoint"  Width="200">
   <Rectangle Stretch="Fill" Fill="Red"/>            
</Popup>

コードビハインドで、このmousemoveイベントを追加します

   pop.MouseMove += new MouseEventHandler(pop_MouseMove);

   void pop_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            pop.PlacementRectangle = new Rect(new Point(e.GetPosition(this).X,
                e.GetPosition(this).Y),new Point(200,200));

        }
    }
17
Jobi Joy

これを実現する別の方法は、ポップアップの配置をMousePointに設定することです。これにより、ポップアップが最初にマウスカーソルの位置に表示されます。

次に、ThumbまたはMouseMoveイベントを使用して、ポップアップのHorizo​​ntalOffsetとVerticalOffsetを設定できます。これらのプロパティは、ユーザーがポップアップをドラッグすると、ポップアップを元の位置から移動します。

ポップアップを次に使用するために、Horizo​​ntalOffsetとVerticalOffsetをゼロにリセットすることを忘れないでください。

2
Ashley Davis

動きが速すぎるとマウスを失う問題は解決できました


これはmsdnから取得されます:

新しいウィンドウには、ポップアップの子コンテンツが含まれています。

ポップアップコントロールは、その子コンテンツへの参照を論理的な子として維持します。新しいウィンドウが作成されると、ポップアップのコンテンツはウィンドウの視覚的な子になり、ポップアップの論理的な子のままになります。逆に、ポップアップは子コンテンツの論理的な親のままです。


つまり、ポップアップの子はスタンドアロンウィンドウに表示されます。

したがって、次のことを試みる場合:
Popup.CaptureMouse()は、ポップアップ自体ではなく、ラッパーウィンドウをキャプチャしています。代わりにPopup.Child.CaptureMouse()を使用すると、実際のポップアップがキャプチャされます。

また、他のすべてのイベントはPopup.Childを使用して登録する必要があります。

Popup.Child.MouseMovePopup.Child.LostCaptureなどのように

これはテスト済みで、完全に正常に機能します

2
Leon

Jobi Joy の答えから構築して、既存のコントロール/ページのxaml内にコントロールとして追加できる再利用可能なソリューションを見つけました。スコープが異なるため、名前付きのXamlとして追加することはできませんでした。

    [ContentProperty("Child")]
    [DefaultEvent("Opened")]
    [DefaultProperty("Child")]
    [Localizability(LocalizationCategory.None)]
    public class DraggablePopup : Popup
    {
        public DraggablePopup()
        {
            MouseDown += (sender, e) =>
            {
                Thumb.RaiseEvent(e);
            };

            Thumb.DragDelta += (sender, e) =>
            {
                HorizontalOffset += e.HorizontalChange;
                VerticalOffset += e.VerticalChange;
            };
        }

        /// <summary>
        /// The original child added via Xaml
        /// </summary>
        public UIElement TrueChild { get; private set; }

        public Thumb Thumb { get; private set; } = new Thumb
        {
            Width = 0,
            Height = 0,
        };

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            TrueChild = Child;

            var surrogateChild = new StackPanel();

            RemoveLogicalChild(TrueChild);

            surrogateChild.Children.Add(Thumb);
            surrogateChild.Children.Add(TrueChild);

            AddLogicalChild(surrogateChild);
            Child = surrogateChild;
        }
    }
0
Gregory A. Owen
Private Point startPoint;

 private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {

        startPoint = e.GetPosition(null);
    }
private void Window_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            Point relative = e.GetPosition(null);
            Point AbsolutePos = new Point(relative.X + this.Left, relative.Y + this.Top);
            this.Top = AbsolutePos.Y - startPoint.Y;
            this.Left = AbsolutePos.X - startPoint.X;
        }
    }

これはウィンドウをドラッグするために機能しますが、マウスを高速に動かすと言われたように、ウィンドウから出てイベントの発生を停止します。言うまでもなく、ドラッグはまったくスムーズではありません。ドラッグが速すぎても失うことなく、適切にドラッグする方法を知っている人はいますか?可能であれば、私のような初心者がコードで迷子になるチュートリアル全体以外の簡単な例を投稿してください。ありがとう!

0
user722886