I have created a usercontrol which uses
<UserControl .......
MouseMove="UserControl_MouseMove"
MouseLeftButtonUp="UserControl_MouseLeftButtonUp">
My PopUp section of the code:
<Popup Name="CustomTablePopup" Placement="Center" IsOpen="False" PopupAnimation="Slide" MouseLeftButtonDown="CustomTablePopup_MouseLeftButtonDown" AllowsTransparency="True">
<Border x:Name="roundBorder" BorderThickness="0" CornerRadius="10" Background="Yellow">
<Border.Effect>
<DropShadowEffect Color="Black" Direction="-360" ShadowDepth="40" Opacity="0.7" />
</Border.Effect>
<Grid Width="Auto" Height="Auto" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- PopUp Header -->
<!-- Style for the Border Colour -->
<Rectangle Grid.Row="0" Fill="Gold" Opacity="0.8"/>
<Grid x:Name="GridHeader" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<!-- PopUp Window Buttons -->
<Border Grid.Column="3" HorizontalAlignment="Right">
<Grid Background="Gold" Opacity="0.8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Style="{DynamicResource HeaderButtonStyle}" Grid.Column="2" Background="Transparent" BorderBrush="Transparent" Click="CloseButton_Click">
<StackPanel Orientation="Horizontal">
<Image RenderOptions.BitmapScalingMode="HighQuality" Source="/Resources/close-window-image.png"/>
</StackPanel>
</Button>
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="1" Content="This is the Custom Table Popup"/>
</Grid>
</Grid>
</Border>
</Popup>
and I have created a singleton class which only updates once the parameter changes:
public class PopUpMovement
{
private PopUpMovement() { }
private static PopUpMovement _instance;
private static readonly object _instanceLock = new object();
public static PopUpMovement Instance()
{
if (_instance == null)
{
lock (_instanceLock)
{
if (_instance == null)
{
_instance = new PopUpMovement();
}
}
}
return _instance;
}
public bool draggingPopup { get; set; }
public bool CustomTablePopupClicked { get; set; }
}
My code in the code behind of usercontrol:
private Point startPoint;
private double initialHorizontalOffset;
private double initialVerticalOffset;
private Point initialMousePosition;
private Point startDragPoint;
//private bool CustomTablePopupClicked;
public UserControlPage()
{
InitializeComponent();
CustomTablePopup.MouseMove += UserControl_MouseMove;
CustomTablePopup.MouseLeftButtonDown += CustomTablePopup_MouseLeftButtonDown;
CustomTablePopup.MouseLeftButtonUp += UserControl_MouseLeftButtonUp;
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
if (CustomTablePopup.IsOpen == true)
{
CustomTablePopup.IsOpen = false;
}
}
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
if (PopUpMovement.Instance().draggingPopup)
{
else if (PopUpMovement.Instance().CustomTablePopupClicked)
{
Point currentMousePosition = e.GetPosition(this); // Get the mouse position relative to the UserControl
double offsetX = currentMousePosition.X - initialMousePosition.X;
double offsetY = currentMousePosition.Y - initialMousePosition.Y;
CustomTablePopup.HorizontalOffset += offsetX;
CustomTablePopup.VerticalOffset += offsetY;
initialMousePosition = currentMousePosition; // Update initial position
}
}
}
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if(PopUpMovement.Instance().draggingPopup == true)
{
PopUpMovement.Instance().draggingPopup = false;
PopUpMovement.Instance().CustomTablePopupClicked = false;
Mouse.Capture(null);
}
}
private void CustomTablePopup_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Store the mouse position
//draggingPopup = true;
//PopUpMovement popUpMovement = PopUpMovement.Instance();
//popUpMovement.draggingPopup = true;
PopUpMovement.Instance().draggingPopup = true;
initialMousePosition = e.GetPosition(this); // Get the mouse position relative to the Window
Mouse.Capture(this); // Capture mouse at the UserControl level
}
It works fine if the user moves the popup window for the first time, however, if the user wants to move it again nothing happens it stays fixed. So, How can I fix the code so that the user can move the popup box anywhere the user wants?
It's not clear to me what your snippets are doing. And due to the lack of details I'm not able to review and fix your code so I decided to provide you with a general solution that couldn't get any simpler and also eliminates the pointless and ugly Singleton.
To make a Popup
draggable you first should attach the event handlers directly to the Popup
. Then ensure a drag target by wrapping the content of the Popup
into a Border
with the Border.Background
set to Transparent
(or any other brush. Just ensure the value is not null
). If you have Popup.AllowsTransparency
set to true
then a Transparent
background is not an option.
Then you must filter the clicked element: for example, you don't want to drag the Popup
if the user clicks into a TextBox
. Instead, you would want to allow the TextBox
to select text.
<UserControl>
<Popup IsOpen="True"
PreviewMouseDown="Popup_PreviewMouseDown"
PreviewMouseMove="Popup_PreviewMouseMove">
<Border Background="White"
Padding="8">
<TextBox Text="I'm a Popup" />
</Border>
</Popup>
</UserControl>
private Point lastDragPosition;
private bool isDragging;
private void Popup_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
this.isDragging = e.OriginalSource is FrameworkElement clickedElement
&& clickedElement.Parent is Popup;
if (!this.isDragging)
{
return;
}
this.lastDragPosition = e.GetPosition(this);
}
private void Popup_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!this.isDragging
|| e.LeftButton is MouseButtonState.Released)
{
return;
}
Point currentDragPosition = e.GetPosition(this);
double horizontalOffset = currentDragPosition.X - this.lastDragPosition.X;
double verticalOffset = currentDragPosition.Y - this.lastDragPosition.Y;
this.lastDragPosition = currentDragPosition;
var popup = (Popup)sender;
popup.HorizontalOffset += horizontalOffset;
popup.VerticalOffset += verticalOffset;
}