Я создал пользовательский элемент управления, который использует
<UserControl .......
MouseMove = "UserControl_MouseMove"
MouseLeftButtonUp = "UserControl_MouseLeftButtonUp">
Мой раздел PopUp кода:
<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>
и я создал одноэлементный класс, который обновляется только после изменения параметра:
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; }
}
Мой код в коде 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
}
Это работает нормально, если пользователь перемещает всплывающее окно в первый раз, однако, если пользователь хочет переместить его снова, ничего не происходит, оно остается фиксированным. Итак, как я могу исправить код, чтобы пользователь мог перемещать всплывающее окно куда угодно?
Свойства PopUpMovement действительно должны быть членами UserControl. Класс «А» никогда не должен хранить состояние другого класса «Б». Каждый класс должен управлять своим состоянием (за исключением того, что класс «А» является структурой данных).
Мы говорим о перетаскивании элемента управления Popup
или вы создаете собственное всплывающее окно? Является ли UserControl всплывающим окном? Что такое CustomTablePopup
? Это Popup
?
@BionicCode, спасибо за комментарии. Моя цель — сделать всплывающее окно перетаскиваемым, мне удалось этого добиться, если я попытаюсь переместить его в первый раз. Однако, если я попробую еще раз, этого не произойдет, оно останется зафиксированным на том месте, где я оставил всплывающее окно. Да, «CustomTablePopup» — это всплывающее окно в коде xaml.
Мне не ясно, что делают ваши фрагменты. Из-за отсутствия подробностей я не могу просмотреть и исправить ваш код, поэтому решил предоставить вам общее решение, которое не может быть проще, а также устраняет бессмысленный и уродливый синглтон.
Чтобы создать перетаскиваемый элемент Popup
, сначала необходимо прикрепить обработчики событий непосредственно к элементу Popup
. Затем обеспечьте цель перетаскивания, обернув содержимое Popup
в Border
с Border.Background
, установленным на Transparent
(или любую другую кисть. Просто убедитесь, что значение не равно null
). Если для Popup.AllowsTransparency
установлено значение true
, фон Transparent
не подойдет.
Затем вы должны отфильтровать выбранный элемент: например, вы не хотите перетаскивать Popup
, если пользователь нажимает на TextBox
. Вместо этого вы хотели бы разрешить TextBox
выбирать текст.
<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;
}
Я изменил вопрос, включив в него код xaml для моего всплывающего окна.
Я вежливо попросил вас опубликовать минимальный воспроизводимый пример. Вместо этого вы продолжаете публиковать фрагменты кода, которые даже не компилируются. Вам не хватает закрывающих тегов, ваши операторы if полностью сломаны, и вы не показали, как установлен соответствующий CustomTablePopupClicked. Вам действительно трудно помочь вам. Либо используйте мой код и интегрируйте его в свое приложение, либо опубликуйте минимальный воспроизводимый пример. Бессмысленно просматривать сломанные фрагменты кода без их контекста. Я не могу сказать, что такое опечатки, а что на самом деле ошибки. Также покажите, как вы показываете/скрываете всплывающее окно.
Пожалуйста, приложите к своему вопросу столько же усилий, сколько вы хотите увидеть в ответе. Я думаю, вы сочтете ответ не очень полезным, если он содержит неработающие фрагменты кода или безумно отформатирован. Пожалуйста. Не тратьте наше время. Мне жаль, что мне приходится быть таким прямым. Надеюсь, вы понимаете суть.
Большую часть времени ошибка скрывается за деталями. Помимо того, что ваш код ужасно сломан, похоже, его недостаточно, чтобы воспроизвести такое поведение. Пожалуйста, создайте полный минимальный пример, который содержит только абсолютный минимум кода, необходимый для запуска нежелательного поведения.
Благодарим вас за ваши комментарии и приносим извинения за то, что не предоставили необходимый код, который помог бы решить эту проблему. Я подумал о том, чтобы указать области, в которых, по моему мнению, могут возникнуть проблемы, я изучил код xaml и обнаружил, что проблем со страницей просмотра пользовательского элемента управления не обнаружено, поэтому я подумал, что проблема будет в коде.
Да, но ваш код неполный. Также интересно, как вы показываете/скрываете всплывающее окно, поскольку это также может повлиять на поведение вашего кода. Мне нужен весь соответствующий код, чтобы правильно его просмотреть. Дело не в ваших расчетах. Однако спасибо за понимание того, что проверка кода возможна только тогда, когда показан весь связанный код и сам код можно собрать.
Я снова отредактировал вопрос. Достаточно ли этих сведений, чтобы воспроизвести проблему и предоставить информацию о том, в чем может быть проблема?
Мне удалось решить свою проблему. Я понял, что когда я перемещаю всплывающее окно и отпускаю его, я устанавливаю для CustomTablePopupClicked значение false, хотя мне не следует этого делать. Теперь я могу перемещать всплывающее окно несколько раз.
Рад, что у вас получилось. Но видите? Я спросил об этом конкретном контексте кода обработки CustomTablePopupClicked, и теперь это стало причиной. Если бы вы показали этот код с самого начала, мы бы решили вашу проблему несколько дней назад. Теперь вы должны понять, насколько важны детали. Какой хороший урок вы усвоили :)
Тем не менее, я рад, что вы это исправили. Желаем приятно провести время и насладиться своим проектом.
Зачем этот Синглтон? Опасно хранить данные, связанные с экземплярами (необщие данные) других объектов, в одном элементе, который в основном разделяет все. Каждый может перезаписать это состояние. Этот вид программирования склонен к ошибкам. Вам следует создать новые экземпляры PopUpMovement. Если вы хотите поделиться PopUpMovement, явно поделитесь этим экземпляром. Кроме того, лучше использовать Lazy<T> для создания общего экземпляра Singleton. Но не используйте здесь Singleton. Это не имеет никакого смысла и только открывает двери для ошибок.