question

VijayKamat-1860 avatar image
0 Votes"
VijayKamat-1860 asked ·

Magnetic Usercontrol?

Hi,

I am working on a WPF project where I will launch a new dialog inside a Window. User should be able to drag this dialog box to the edge of the window and if it is close enough, it should cling on to that side of the window like docking. User can detach it and re-attach to another side if he likes.

The dialog I want to drag is actually a usercontrol which sits in a grid column so I cant use DragMove() etc. Also, when I drag it out, it should come out of grid column so I can freely drag it around and when I cling it back to the left border it should sit back in the grid column.

I have tried this for the UserControl:

 private void titleBar_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
          {
              if (e.LeftButton == MouseButtonState.Pressed)
              {
                  mousePosition = e.GetPosition(null);
     
     
                  if (tt.X < 10)
                  {
                     tt.X = 10;
                  }
     
                  if (tt.Y < 10)
                  {
                      tt.Y = 10;
                  }
                  this.RenderTransform = tt;
     
                  var Grid = TreeHelper.FindParent<Grid>(this);
                  Grid.ColumnDefinitions[0].Width = new GridLength(0);
                  Grid.Children.Remove(this);
                  this.Height = 1000;
                  this.Width = 400;
              }
          }
     
          private void TitleBar_OnPreviewMouseMove(object sender, MouseEventArgs e)
          {
              if (e.LeftButton == MouseButtonState.Pressed)
              {
                  tt.X +=  e.GetPosition(null).X - mousePosition.X;
                  tt.Y += e.GetPosition(null).Y - mousePosition.Y;
     
                  mousePosition = e.GetPosition(null);
                     
                  if (tt.X < 10)
                  {
                      tt.X = 0;
                  }
     
                  if (tt.Y < 10)
                  {
                      tt.Y = 0;
                  }
     
                  this.RenderTransform = tt;
              }
          }


But it doesnt work properly. The control disspapears when Grid column size becomes 0 and I remove it from the Grid.

windows-wpf
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AlexLi-MSFT avatar image
0 Votes"
AlexLi-MSFT answered ·

Welcome to Microsoft Q&A platform!

You didn't provide full code,but you can see my example.

xaml:

  <Grid>
         <Grid.ColumnDefinitions>
             <ColumnDefinition />
             <ColumnDefinition/>
         </Grid.ColumnDefinitions>
         <Canvas Grid.Column="0" Background="AliceBlue">
             <local:MyUserControl Width="40" Height="40" Background="Red" x:Name="usercontrol1" Canvas.Top="100" Canvas.Left="100" />
         </Canvas>
     </Grid>

C#

   public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
    
             usercontrol1.PreviewMouseMove += new MouseEventHandler(Element_MouseMove);
             usercontrol1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(Element_MouseLeftButtonDown);
             usercontrol1.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(Element_MouseLeftButtonUp);
         }
    
         bool isDragDropInEffect = false;
         Point pos = new Point();
    
         void Element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         {
    
                
             isDragDropInEffect = true;
             pos = e.GetPosition(null);
             usercontrol1.CaptureMouse();
             usercontrol1.Cursor = Cursors.Hand;
         }
         void Element_MouseMove(object sender, MouseEventArgs e)
         {
             if (isDragDropInEffect)
             {
                   
                 double xPos = e.GetPosition(null).X - pos.X + (double)usercontrol1.GetValue(Canvas.LeftProperty);
                 double yPos = e.GetPosition(null).Y - pos.Y + (double)usercontrol1.GetValue(Canvas.TopProperty);
                 usercontrol1.SetValue(Canvas.LeftProperty, xPos);
                 usercontrol1.SetValue(Canvas.TopProperty, yPos);
                 pos = e.GetPosition(null);
             }
         }
    
    
    
         void Element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
         {
             if (isDragDropInEffect)
             {
                    
                 isDragDropInEffect = false;
                 usercontrol1.ReleaseMouseCapture();
             }
    
             if ((double)usercontrol1.GetValue(Canvas.LeftProperty) < 50)
             {
                 double i = -30;
                 usercontrol1.SetValue(Canvas.LeftProperty, i );
              
             }
         }
    
    
     }
     public class MyUserControl : UserControl
     {
    
     }

7598-1.gif




Thanks.


1.gif (58.5 KiB)
· 4 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.


Thank you for the reply, but as I have said in my question, I ahve a grid, not a canvas.

Somehting like this:


 <Grid>
 <ColumnDefinitions>
 <ColumnDefinition/>
 <ColumnDefinition/>
 **<UserControl Grid.Column="0">**
 <Some other thingGrid.Column="1">
 </Gri>



So I cant use your solution. The user control has to come out of grid cilumn adn then go back in. Or something else to give that effect.

0 Votes 0 ·

Can you provide full mode for I can test it?

0 Votes 0 ·

Please my post below as I cant put more than 1000 charaters here.

0 Votes 0 ·

Any idea if this can be done?

0 Votes 0 ·
VijayKamat-1860 avatar image
0 Votes"
VijayKamat-1860 answered ·

Main Window:

 <Window x:Class="WpfApp1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:WpfApp1"
         mc:Ignorable="d"
         Name="MyWindow"
         Title="MainWindow" Height="450" Width="800">
     <Grid>
         <Grid.ColumnDefinitions>
             <ColumnDefinition>
                 <ColumnDefinition.Style>
                     <Style TargetType="ColumnDefinition">
                         <Setter Property="Width"
                                 Value="0" />
                         <Style.Triggers>
                             <DataTrigger Binding="{Binding PanelExpanded,ElementName=MyWindow, Mode=TwoWay}"
                                          Value="True">
                                 <Setter Property="Width"
                                         Value="{Binding PanelWidth, ElementName=MyWindow}" />
                             </DataTrigger>
                         </Style.Triggers>
                     </Style>
                 </ColumnDefinition.Style>
             </ColumnDefinition>
             <ColumnDefinition 
                               Width="*" />
             </Grid.ColumnDefinitions>
            
         <local:MyUserControl Grid.Column="0"/>
    
         <TabControl Grid.Column="1"/>
    
     </Grid>
 </Window>


Code Behind Main Window:

  public partial class MainWindow : Window
     {
         public bool PanelExpanded { get; set; }
    
    
         public double PanelWidth { get; set; }
    
         public MainWindow()
         {
             PanelExpanded = true;
             PanelWidth = 150;
    
             InitializeComponent();
         }
    
    
     }


My User control:


  <Grid>
         <Grid>
             <Grid.RowDefinitions>
                 <RowDefinition Height="30" />
                 <RowDefinition Height="*" />
             </Grid.RowDefinitions>
             <Border Name="titleBar"
                     Grid.Row="0"
                     HorizontalAlignment="Stretch"
                     VerticalAlignment="Stretch"
                     Background="Gray"
                     PreviewMouseLeftButtonDown="titleBar_OnPreviewMouseLeftButtonDown"
                     PreviewMouseMove="TitleBar_OnPreviewMouseMove" />
    
                
         </Grid>
     </Grid>

Code Behind My user control:


public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
tt = new TranslateTransform();
}

     private Point mousePosition;
     private TranslateTransform tt;

     private void titleBar_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
     {
         if (e.LeftButton == MouseButtonState.Pressed)
         {
             mousePosition = e.GetPosition(null);


             if (tt.X < 10)
             {
                 //tt.X = 10;
             }

             if (tt.Y < 10)
             {
                 // tt.Y = 10;
             }


             var Grid = FindParent<Grid>(this);
             Grid.ColumnDefinitions[0].Width = new GridLength(0);

             if (Grid.GetColumn(this) == 0)
             {
                 Grid.SetColumn(this, 1);
                 Grid.SetColumnSpan(this, 2);

                 tt.X = 10;
                 tt.Y = 10;
                 this.RenderTransform = tt;


                 this.Height = 400;
                 this.Width = 150;
             }
         }
     }

     private void TitleBar_OnPreviewMouseMove(object sender, MouseEventArgs e)
     {
         if (e.LeftButton == MouseButtonState.Pressed)
         {
             tt.X += e.GetPosition(null).X - mousePosition.X;
             tt.Y += e.GetPosition(null).Y - mousePosition.Y;

             mousePosition = e.GetPosition(null);

             if (tt.X < 10)
             {
                 //tt.X = 0;
             }

             if (tt.Y < 10)
             {
                 //tt.Y = 0;
             }

             this.RenderTransform = tt;
         }
     }

     public static T FindParent<T>(DependencyObject child) where T : DependencyObject
     {
         //get parent item
         DependencyObject parentObject = VisualTreeHelper.GetParent(child);

         //we've reached the end of the tree
         if (parentObject == null) return null;

         //check if the parent matches the type we're looking for
         T parent = parentObject as T;
         if (parent != null)
             return parent;
         else
             return FindParent<T>(parentObject);
     }

 }


·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.