עשיתי קוד שיוצר תכונת snap על ידי כפתורים דינמיים עבור usercontrol בwpf
נתקלתי בבעיה שבפעם הרשונה שהכפתורים נטענים המיקום שלהם משובש.
מצו:ב הקוד
<UserControl x:Class="test_wpf_snap.UserControl3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
MouseLeftButtonDown="UserControl_MouseLeftButtonDown"
MouseMove="UserControl_MouseMove"
MouseLeftButtonUp="UserControl_MouseLeftButtonUp"
BorderBrush="Black"
d:DesignHeight="100" d:DesignWidth="100">
<UserControl.Background>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ControlColorKey}}"/>
</UserControl.Background>
<Grid Width="100" Height="100">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToolBar Grid.Row="0">
</ToolBar>
<DockPanel >
<DockPanel.Background>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.WindowColorKey}}"/>
</DockPanel.Background>
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Content="X" Width="25" DockPanel.Dock="Right" HorizontalAlignment="Right"/>
</DockPanel>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
namespace test_wpf_snap
{
/// <summary>
/// Interaction logic for UserControl3.xaml
/// </summary>
public partial class UserControl3 : UserControl
{
private bool inDrag = false;
private Point anchorPoint;
private bool showSnapButtons = false;
SnapButtons snapButtons;
public UserControl3()
{
InitializeComponent();
snapButtons = new SnapButtons(this);
}
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!inDrag)
{
anchorPoint = e.GetPosition(null);
CaptureMouse();
inDrag = true;
snapButtons.ShowSnapButtons();
e.Handled = true;
}
}
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
if (inDrag)
{
Point currentPoint = e.GetPosition(null);
// Move the UserControl
Canvas.SetLeft(this, Canvas.GetLeft(this) + (currentPoint.X - anchorPoint.X));
Canvas.SetTop(this, Canvas.GetTop(this) + (currentPoint.Y - anchorPoint.Y));
anchorPoint = currentPoint;
snapButtons.HighlightSnapButtonIfMouseOver(snapButtons.snapTopButton, e);
snapButtons.HighlightSnapButtonIfMouseOver(snapButtons.snapBottomButton, e);
snapButtons.HighlightSnapButtonIfMouseOver(snapButtons.snapLeftButton, e);
snapButtons.HighlightSnapButtonIfMouseOver(snapButtons.snapRightButton, e);
}
e.Handled = true;
}
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (inDrag)
{
ReleaseMouseCapture();
inDrag = false;
snapButtons.HideSnapButtons();
e.Handled = true;
}
}
}
}
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace test_wpf_snap
{
public class SnapButtons
{
public Button snapTopButton;
public Button snapBottomButton;
public Button snapLeftButton;
public Button snapRightButton;
private UserControl snapControl;
private bool showSnapButtons;
public SnapButtons(UserControl control)
{
InitializeSnapButtons();
snapControl = control;
}
private void InitializeSnapButtons()
{
snapTopButton = CreateSnapButton("Snap\r\nTop", "SnapToTop");
snapBottomButton = CreateSnapButton("Snap\r\nBottom", "SnapToBottom");
snapLeftButton = CreateSnapButton("Snap\r\nLeft", "SnapToLeft");
snapRightButton = CreateSnapButton("Snap\r\nRight", "SnapToRight");
HideSnapButtons();
}
private Button CreateSnapButton(string buttonText, string tag)
{
var button = new Button { Content = CreateCenteredTextBlock(buttonText), Tag = tag };
SetButtonStyle(button);
return button;
}
private TextBlock CreateCenteredTextBlock(string text)
{
var textBlock = new TextBlock
{
FontSize = 9,
Text = text,
TextAlignment = TextAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Stretch
};
return textBlock;
}
private void SetButtonStyle(Button button)
{
button.Background = Brushes.Transparent;
button.Foreground = Brushes.Black;
button.Width = 30;
button.Height = 30;
button.MouseEnter += (sender, e) => SnapToPosition((Button)sender);
}
private void SnapToPosition(Button button)
{
double targetLeft = Canvas.GetLeft(snapControl);
double targetTop = Canvas.GetTop(snapControl);
switch (button.Tag.ToString())
{
case "SnapToTop":
targetTop = 0;
break;
case "SnapToBottom":
targetTop = ((Canvas)snapControl.Parent).ActualHeight - snapControl.ActualHeight;
break;
case "SnapToLeft":
targetLeft = 0;
break;
case "SnapToRight":
targetLeft = ((Canvas)snapControl.Parent).ActualWidth - snapControl.ActualWidth;
break;
}
Canvas.SetLeft(snapControl, targetLeft);
Canvas.SetTop(snapControl, targetTop);
}
public void HighlightSnapButtonIfMouseOver(Button button, MouseEventArgs e)
{
Point mousePosition = e.GetPosition(button);
if (mousePosition.X >= 0 && mousePosition.X <= button.ActualWidth &&
mousePosition.Y >= 0 && mousePosition.Y <= button.ActualHeight)
{
// Use system default highlight color
button.Background = SystemColors.ActiveCaptionBrush;
}
else
{
// Remove highlighting if the mouse is not over the button
button.Background = Brushes.Transparent;
}
}
public void ShowSnapButtons()
{
if (showSnapButtons)
return;
Canvas canvas = snapControl.Parent as Canvas;
if (canvas == null)
return;
double centerX = Canvas.GetLeft(snapControl) + snapControl.ActualWidth / 2;
double centerY = Canvas.GetTop(snapControl) + snapControl.ActualHeight / 2;
double buttonSeparation = 10;
// Set the position of the imaginary center button
SetSnapButtonPosition(snapBottomButton, centerX, centerY);
// Adjust other buttons relative to the imaginary center button
SetSnapButtonPosition(snapTopButton, centerX, centerY - snapTopButton.ActualHeight - buttonSeparation);
SetSnapButtonPosition(snapLeftButton, centerX - snapLeftButton.ActualWidth - buttonSeparation, centerY);
SetSnapButtonPosition(snapRightButton, centerX + snapBottomButton.ActualWidth + buttonSeparation, centerY);
// Apply styles and add buttons to the canvas
foreach (Button button in new[] { snapTopButton, snapBottomButton, snapLeftButton, snapRightButton })
{
canvas.Children.Add(button);
}
showSnapButtons = true;
}
private void SetSnapButtonPosition(Button button, double left, double top)
{
Canvas.SetLeft(button, left - button.ActualWidth / 2);
Canvas.SetTop(button, top - button.ActualHeight / 2);
}
public void HideSnapButtons()
{
if (showSnapButtons)
{
// Remove snap buttons from the Canvas
Canvas canvas = snapControl.Parent as Canvas;
canvas?.Children.Remove(snapTopButton);
canvas?.Children.Remove(snapBottomButton);
canvas?.Children.Remove(snapLeftButton);
canvas?.Children.Remove(snapRightButton);
showSnapButtons = false;
}
}
}
}