Reputation: 467
I used code found here on Stack Overflow to make a WPF popup draggable using attached behavors. This code and behavior works as expected. The popup will remain at its dragged position until the user moves it again.
What I want to do now is make the popup appear at its original placement target location once it is closed and reopened. How do I accomplish this task?
Original post: A draggable popup control in wpf
Answer code written by Rick Sladkey: https://stackoverflow.com/a/4784977/1286413
Here is the XAML for the Popup:
<Grid>
<StackPanel>
<TextBox x:Name="textBox1" Width="200" Height="20"/>
</StackPanel>
<Popup PlacementTarget="{Binding ElementName=textBox1}" IsOpen="{Binding IsKeyboardFocused, ElementName=textBox1, Mode=OneWay}">
<i:Interaction.Behaviors>
<local:MouseDragPopupBehavior/>
</i:Interaction.Behaviors>
<TextBlock Background="White">
<TextBlock.Text>Sample Popup content.</TextBlock.Text>
</TextBlock>
</Popup>
</Grid>
Here is the AttachedBehavior he wrote:
public class MouseDragPopupBehavior : Behavior<Popup>
{
private bool mouseDown;
private Point oldMousePosition;
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonDown += (s, e) =>
{
mouseDown = true;
oldMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
AssociatedObject.Child.CaptureMouse();
};
AssociatedObject.MouseMove += (s, e) =>
{
if (!mouseDown) return;
var newMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
var offset = newMousePosition - oldMousePosition;
oldMousePosition = newMousePosition;
AssociatedObject.HorizontalOffset += offset.X;
AssociatedObject.VerticalOffset += offset.Y;
};
AssociatedObject.MouseLeftButtonUp += (s, e) =>
{
mouseDown = false;
AssociatedObject.Child.ReleaseMouseCapture();
};
}
}
Thanks in advance for the help!
Upvotes: 2
Views: 1685
Reputation: 1964
In OnAttached, add a handler to Closed that will save the popup's position, and another handler to Opened that will move the popup back to that position.
public class MouseDragPopupBehavior : Behavior<Popup>
{
private bool mouseDown;
private Point oldMousePosition;
private bool useSavedPosition;
private Point savedPosition;
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonDown += (s, e) =>
{
mouseDown = true;
oldMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
AssociatedObject.Child.CaptureMouse();
};
AssociatedObject.MouseMove += (s, e) =>
{
if (!mouseDown) return;
var newMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
var offset = newMousePosition - oldMousePosition;
oldMousePosition = newMousePosition;
AssociatedObject.HorizontalOffset += offset.X;
AssociatedObject.VerticalOffset += offset.Y;
};
AssociatedObject.MouseLeftButtonUp += (s, e) =>
{
mouseDown = false;
AssociatedObject.Child.ReleaseMouseCapture();
};
AssociatedObject.Opened += (s, e) =>
{
if (!useSavedPosition) return;
AssociatedObject.HorizontalOffset = savedPosition.X;
AssociatedObject.VerticalOffset = savedPosition.Y;
};
AssociatedObject.Loaded += (s, e) =>
{
savedPosition = new Point(AssociatedObject.HorizontalOffset, AssociatedObject.VerticalOffset);
useSavedPosition = true;
};
}
}
Upvotes: 2