user1805087
user1805087

Reputation: 97

Draggable silverlight user control

I created a draggaable user control in silverlight, but having issues in moving the control inside page. Actually the issue is, dragged control moves out of page when dragging which i don't want. I want the control should drag inside the parent control only.

Any help/suggestion would be appreciated.

enter image description here

Below is the code used to perform operation:
XAML:
<Grid x:Name="LayoutRoot" >
        <Grid.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform/>
                <TranslateTransform x:Name="LocalTranslateTransform"/>
            </TransformGroup>
        </Grid.RenderTransform>
C#:
private void OnToolbarClicked(object sender, MouseButtonEventArgs e)
{
    mouseDownInToolbar = true;
    DragOffset = e.GetPosition(LayoutRoot);
    toolbarBorder.CaptureMouse();
}

private void OnToolbarMoving(object sender, MouseEventArgs e)
{
    if (mouseDownInToolbar)
    {
        // we want to move it based on the position of the mouse
        moveUserControl(e);
    }
}

private void moveUserControl (MouseEventArgs e)
{
    Point mousePos = e.GetPosition(LayoutRoot);
    Double newX = LocalTranslateTransform.X + (mousePos.X - DragOffset.X);
    Double newY = LocalTranslateTransform.Y + (mousePos.Y - DragOffset.Y);
    LocalTranslateTransform.X = newX;
    LocalTranslateTransform.Y = newY;
}

private void OnToolbarReleased(object sender, MouseButtonEventArgs e)
{
    mouseDownInToolbar = false;
    toolbarBorder.ReleaseMouseCapture();
}

Upvotes: 2

Views: 100

Answers (1)

Laith
Laith

Reputation: 6091

When you use TranslateTransform, you're sending instructions to the compositor thread to display the element at X/Y offsets. It does not obey the rules of your panel and any visual tree member. So, you have to tell the compositor thread about the boundaries. Use Clip like this:

<Grid Width="500" Height="500">
  <Grid.Clip>
       <RectangleGeometry Rect="0,0,500,500" /> 
   </Grid.Clip>

   <Grid x:Name="LayoutRoot">
        <!-- This is the element being dragged by the mouse -->
   </Grid>
</Grid>

The RectangleGeometry will create a boundary where child elements are allowed to appear. Anything outside, will be clipped.


After doing the desired changes this is how it looked.

enter image description here


You need to create a constraint.

Calculate if you're transforming the actual control outside the bounds of the parent.

private void moveUserControl (MouseEventArgs e)
{
    Point mousePos = e.GetPosition(LayoutRoot);
    Double newX = LocalTranslateTransform.X + (mousePos.X - DragOffset.X);
    Double newY = LocalTranslateTransform.Y + (mousePos.Y - DragOffset.Y);

    var minX = 0;
    var maxX = 500 - ActualWidth; // 500 is parent width
    var minY = 0;
    var maxY = 500 - ActualHeight; // 500 is parent height

    if (newX < minX)
    {
        newX = minX;
    }
    else if (newX > maxX)
    {
        newX = maxX;
    } 

    if (newY < minY)
    {
        newY = minY;
    }
    else if (newY > maxY)
    {
        newY = maxY;
    } 

    LocalTranslateTransform.X = newX;
    LocalTranslateTransform.Y = newY;
}

Upvotes: 4

Related Questions