Click here to Skip to main content
Click here to Skip to main content

WPF Diagram Designer: Part 1

By , 23 Aug 2008
 

Introduction

In this article, I will show you how to move, resize and rotate objects of any type on a canvas. For this, I will provide two different solutions - the first one without and then one with WPF Adorners.

About the Code

The attached Visual Studio Express 2008 solution consists of three projects:

MoveResize: This version shows you how to move and resize objects without WPF Adorners.

MoveResizeRotate: In addition, this project provides rotation of objects, still without WPF Adorners. Rotation has some minor side effects that need to be considered when moving or resizing objects. You can easily track these side effects when you compare this project with the previous one.

MoveResizeRotateWithAdorners: The third project finally shows you how to move, resize and rotate items with the help of WPF Adorners. It also gives you an example of how Adorners can be used to provide visual feedback to indicate the actual size of an object during a resize operation.

Preparations

We start with a simple diagram:

<Canvas>
  <Ellipse Fill="Blue"
           Width="100"
           Height="100"
           Canvas.Top="100"
           Canvas.Left="100"/>
</Canvas>

You might not be impressed by this diagram, nevertheless it is a good starting point. It is easy to understand and it has all a basic diagram needs to have: a drawing canvas with a shape. But you are right, this diagram isn't really useful - it's just too static.

So let's start with some preparations by wrapping the ellipse into a ContentControl:

 <Canvas>      
   <ContentControl Width="100"
                   Height="100"
                   Canvas.Top="100"
                   Canvas.Left="100">
      <Ellipse Fill="Blue"/>
   </ContentControl>
</Canvas>

Not much better you may say, we still can't move the ellipse, so what is it good for? Well, the ContentControl serves as a container for the object that we want to place on the canvas and it is actually this ContentControl that we are going to move, resize and rotate! And because the content of a ContentControl can be of any type, we will be able to move, resize and rotate objects of any type on our canvas!

Note: Because of its key role, this ContentControl is also referred to as DesignerItem.

We conclude our preparations by assigning a ControlTemplate to the DesignerItem. This introduces a further level of abstraction, so that from now on we will just expand this template and leave the DesignerItem and its content completely untouched.

 <Canvas>    
   <Canvas.Resources>
      <ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
         <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
      </ControlTemplate>
   </Canvas.Resources>  
   <ContentControl Name="DesignerItem"
                   Width="100"
                   Height="100"
                   Canvas.Top="100"
                   Canvas.Left="100"
                   Template="{StaticResource DesignerItemTemplate}">
      <Ellipse Fill="Blue"/>
   </ContentControl>
</Canvas>

Now that we have finished our preparations, we are ready to bring some activity on the canvas.

Move

There is a control in WPF about which the MSDN documentation says: " ...represents a control that lets the user drag and resize controls." That seems to be a perfect candidate for our job. It is the Thumb control and here is how we are going to use it:

public class MoveThumb : Thumb
{
    public MoveThumb()
    {
        DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
    }

    private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        Control item = this.DataContext as Control;

        if (item != null)
        {
            double left = Canvas.GetLeft(item);
            double top = Canvas.GetTop(item);

            Canvas.SetLeft(item, left + e.HorizontalChange);
            Canvas.SetTop(item, top + e.VerticalChange);
        }
    }
}

The MoveThumb is inherited from Thumb and it provides just an implementation of the DragDelta event handler. Within the event handler, first the DataContext is cast to a ContentControl and then its position is updated according to the horizontal and vertical drag change. You may have already guessed that the control retrieved from the DataContext is our DesignerItem, but where does it come from? You can find the answer if you look at the updated DesignerItem's template:

 <ControlTemplate x:Key="DesignerItemControlTemplate" TargetType="ContentControl">
  <Grid> 
    <s:DragThumb DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" 
                 Cursor="SizeAll"/> 
    <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
  </Grid> 
</ControlTemplate> 

Here you see that the MoveThumb's DataContext property is bound to the templated parent, which is of course our DesignerItem. Note that we have added a Grid as the layout panel for the template, which allows both the ContentPresenter and the MoveThumb to take in the complete DesignerItem's real estate. Now we can compile and run the code.

Default visual representation of a Thumb control in WPF

As a result, we get a blue ellipse on top of a gray MoveThumb. If you play around with it, you will notice that you can actually grab and drag the object, but only where the gray MoveThumb is visible. That's because the ellipse hinders the mouse events to make its way through to the MoveThumb. We can easily change this behaviour by setting the IsHitTest property of the ellipse to false.

 <Ellipse Fill="Blue" IsHitTestVisible="False"/>

The MoveThumb has inherited its style from the base Thumb class, which is not really appealing in our case. For this, we create a new template consisting of a transparent rectangle only. A more general solution would be to create a default style for the MoveThumb class, but for the moment a customized template will do.

Now the DesignerItem's control template looks like this:

 <ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
  <Rectangle Fill="Transparent"/>
</ControlTemplate>

<ControlTemplate x:Key="DesignerItemTemplate" TargetType="Control">
   <Grid>
     <s:MoveThumb Template="{StaticResource MoveThumbTemplate}"
        DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
        Cursor="SizeAll"/>
     <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
   </Grid>
</ControlTemplate>

That's all we need to move items on a canvas, now I will show you how to resize objects.

Resize

You remember that the MSDN documentation promised that the Thumb control would let the user drag and resize controls? So, we stick with the Thumb control and build a control template, named ResizeDecoratorTeamplate:

 <ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="Control">
  <Grid>
    <Thumb Height="3" Cursor="SizeNS" Margin="0 -4 0 0"
           VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
    <Thumb Width="3" Cursor="SizeWE" Margin="-4 0 0 0"
           VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
    <Thumb Width="3" Cursor="SizeWE" Margin="0 0 -4 0"
           VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
    <Thumb Height="3" Cursor="SizeNS" Margin="0 0 0 -4"
           VerticalAlignment="Bottom"  HorizontalAlignment="Stretch"/>
    <Thumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0"
           VerticalAlignment="Top" HorizontalAlignment="Left"/>
    <Thumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0"
           VerticalAlignment="Top" HorizontalAlignment="Right"/>
    <Thumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6"
           VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
    <Thumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6"
           VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
   </Grid>
 </ControlTemplate>

Here you see a control template that consists of a grid filled up with a bunch of 8 Thumb controls, which should work as resize handles. By setting the Thumb properties like we did above, we achieved a layout that results in something that looks like a real resize decorator:

A resize decorator build with 8 Thumbs

Amazing, isn't it. But so far it is only a fake, because there is no event handler that would handle the DragDelta events of the Thumbs. For this, we replace the Thumb objects by ResizeThumbs:

public class ResizeThumb : Thumb
{
    public ResizeThumb()
    {
        DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
    }

    private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        Control item = this.DataContext as Control;

        if (item != null)
        {
            double deltaVertical, deltaHorizontal;

            switch (VerticalAlignment)
            {
                case VerticalAlignment.Bottom:
                    deltaVertical = Math.Min(-e.VerticalChange, 
                        item.ActualHeight - item.MinHeight);
                    item.Height -= deltaVertical;
                    break;
                case VerticalAlignment.Top:
                    deltaVertical = Math.Min(e.VerticalChange, 
                        item.ActualHeight - item.MinHeight);
                    Canvas.SetTop(item, Canvas.GetTop(item) + deltaVertical);
                    item.Height -= deltaVertical;
                    break;
                default:
                    break;
            }

            switch (HorizontalAlignment)
            {
                case HorizontalAlignment.Left:
                    deltaHorizontal = Math.Min(e.HorizontalChange, 
                        item.ActualWidth - item.MinWidth);
                    Canvas.SetLeft(item, Canvas.GetLeft(item) + deltaHorizontal);
                    item.Width -= deltaHorizontal;
                    break;
                case HorizontalAlignment.Right:
                    deltaHorizontal = Math.Min(-e.HorizontalChange, 
                        item.ActualWidth - item.MinWidth);
                    item.Width -= deltaHorizontal;
                    break;
                default:
                    break;
            }
        }

        e.Handled = true;
    }
}

The ResizeThumbs just update the DesignerItem's width, height and/or position, depending on the ResizeThumb's vertical and horizontal alignment. Now let's integrate the resize decorator into the DesignerItem's control template by adding a Control object with the ResizeDecoratorTemplate.

<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
  <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
    <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
    <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
    <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
  </Grid>
</ControlTemplate>

Perfect, now we can move and resize objects. Next comes rotation of objects.

Rotate

To provide rotation of objects, we follow the same solution path as in the chapter before, but this time we create a RotateThumb and arrange four instances of it in a control template named RotateDecoratorTemplate. Together with the resize decorator, it looks like this:

A rotate decorator build with 4 Thumbs

The structure of the code for RotateThumb and the RotateDecoratorTemplate is very similar to what we have seen in the chapter before, so I will not list the code here.

Note: My first approach to drag, resize and rotate items was to use WPF's TranslateTransform, ScaleTransform and RotateTransform. But that turned out to be the wrong way, because Transforms in WPF do not really change an object's properties like width or height, WPF Transforms are just a rendering issue. So I didn't use TranslateTransform and ScaleTransform to drag and resize items, but I had to use RotateTransform because of no alternative.

DesignerItem Style

For convenience, we wrap the DesignerItem's control template into a style, where we also set various properties like MinWidth, MinHeight and RenderTransformOrigin. A trigger allows us to make the resize and rotate decorator visible only when the item is selected, which is indicated by the attached property Selector.IsSelected.

Note: WPF comes with a class named Selector, which is a control that allows you to select items from among its child elements. I do not make use of this control in this article, but I use the attached Selector.IsSelected property to mimic selection.

 <Style x:Key="DesignerItemStyle" TargetType="ContentControl">
  <Setter Property="MinHeight" Value="50"/>
  <Setter Property="MinWidth" Value="50"/>
  <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ContentControl">
        <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
          <Control x:Name="RotateDecorator" 
                   Template="{StaticResource RotateDecoratorTemplate}" 
                   Visibility="Collapsed"/>
          <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" 
                       Cursor="SizeAll"/>
          <Control x:Name="ResizeDecorator" 
                   Template="{StaticResource ResizeDecoratorTemplate}" 
                   Visibility="Collapsed"/>
          <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="Selector.IsSelected" Value="True">
            <Setter TargetName="ResizeDecorator" 
                Property="Visibility" Value="Visible"/>
            <Setter TargetName="RotateDecorator" 
                Property="Visibility" Value="Visible"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>  

That's it. Now we can move, resize and rotate objects. One has to realize that a few lines of XAML code together with three classes provide all we need to do that! Best of all, we don't need to touch the objects themselves: all the behaviour is completely wrapped into a ControlTemplate.

Adorner Based Solution

In this chapter, I present a solution that raises the resize and rotate decorators to the AdornerLayer so that they are rendered on top of all other items.

The adorner based solution is best explained by showing you the resulting DesignerItem's control template:

 <ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
  <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
    <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
    <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
    <s:DesignerItemDecorator x:Name="decorator" ShowDecorator="true"/>
  </Grid>
  <ControlTemplate.Triggers>
    <Trigger Property="Selector.IsSelected" Value="True">
      <Setter TargetName="decorator" Property="ShowDecorator" Value="true"/>
    </Trigger>      
  </ControlTemplate.Triggers>
</ControlTemplate>

This template is similar to what we had in the previous chapter, except that the resize and rotate decorators are replaced by an instance of a new class named DesignerItemDecorator. This class is derived from Control and has no own default style, instead the class provides an adorner that becomes visible when the boolean ShowAdorner property gets true.

 public class DesignerItemDecorator : Control
{
    private Adorner adorner;

    public bool ShowDecorator
    {
        get { return (bool)GetValue(ShowDecoratorProperty); }
        set { SetValue(ShowDecoratorProperty, value); }
    }

    public static readonly DependencyProperty ShowDecoratorProperty =
        DependencyProperty.Register
            ("ShowDecorator", typeof(bool), typeof(DesignerItemDecorator),
        new FrameworkPropertyMetadata
            (false, new PropertyChangedCallback(ShowDecoratorProperty_Changed)));


    private void HideAdorner()
    {
        ...
    }

    private void ShowAdorner()
    {
        ...
    }

    private static void ShowDecoratorProperty_Changed
        (DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DesignerItemDecorator decorator = (DesignerItemDecorator)d;
        bool showDecorator = (bool)e.NewValue;

        if (showDecorator)
        {
            decorator.ShowAdorner();
        }
        else
        {
            decorator.HideAdorner();
        }
    }
}

The adorner that becomes visible when the DesignerItem is selected is of type DesignerItemAdorner and is derived from Adorner:

 public class DesignerItemAdorner : Adorner
{
    private VisualCollection visuals;
    private DesignerItemAdornerChrome chrome;

    protected override int VisualChildrenCount
    {
        get
        {
            return this.visuals.Count;
        }
    }

    public DesignerItemAdorner(ContentControl designerItem)
         : base(designerItem)
    {
        this.chrome = new DesignerItemAdornerChrome();
        this.chrome.DataContext = designerItem;
        this.visuals = new VisualCollection(this);         
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        this.chrome.Arrange(new Rect(arrangeBounds));
        return arrangeBounds;
    }

    protected override Visual GetVisualChild(int index)
    {
        return this.visuals[index];
    }
}

You see that this adorner has a single visual child of type DesignerItemAdornerChrome, which is actually the control that provides the drag handles to resize and rotate items. This chrome control has a default style which arranges ResizeThumbs and RotateThumbs objects in a way that is similar to what we have seen in the previous chapter, so I will not repeat that code here.

Custom Adorners

You can, of course, add your own customized adorners to a DesignerItem. As an example, I have added an adorner that displays width and height while resizing an object. For more details, please see the attached code. If you have questions, feel free to ask.

History

  • 10th January, 2008 -- Original version
  • 18th January, 2008 -- Update: Introduced ContentControl as designer item
  • 5th February, 2008 -- Update: Added rotation of items
  • 22nd August, 2008 -- Update: Added adorner based solution

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

sukram
Austria Austria
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhow to make movable inner connected objects, help me, please!memberDuška Miloradović21 May '13 - 1:59 
I have a graph representation, which is a set of nodes(circles) connected with edges(lines), and I want to make that nodes movable all together with incident edges. I tried with your example, but all I get is moving of whole graph only. Big Grin | :-D Do you have some suggestions to help me to make inner elements movable, please?
I don't know how to force nodes and edges to 'draw' themselves with bindings so it wouldn't be an Image anymore (I was using DrawingImage).
QuestionPerfect!memberevrenG26 Apr '13 - 10:02 
I ve seen in the net many examples regarding adorners & co, yours is compact, well structured and easy to understand. Besides even after years (your project was of VS2008) the sample is still intact and upgradable, that is what i call simplicity. Thanks for writing compact examples...keep up good work!
GeneralMy vote of 4memberschmiddd20 Apr '13 - 6:14 
Code works great, but could explaind more in depth. Adding the the logic to select the shape took me some time. Curently realized it by adding another, invisible button which switches its IsHitTestVisible, when the button is clicked, to enable the move,rotate and resize manipulations.
GeneralMy vote of 3memberFrancisco T. Chavez15 Mar '13 - 10:43 
The further you get into the article, the more the source code differs from what the article tells us what to do. Also, when we get into a control that does something a bit more complicated, he says it's similar to control X so I won't be writing down the code here. I can still piece things together between the article and the code, and I also learn new things that I didn't know before but wanted to know how to do. That's the minimum of passing, which is where it get's a 3. I would have given it a 4, but the classes mentioned in the last section don't match up with what's in the source code.
Generalmy vote of 5memberMember 822540725 Nov '12 - 3:55 
perfect code
thanks so much
GeneralMy vote of 5memberMember 822540725 Nov '12 - 3:54 
perfect code
thanks so much
QuestionSelect and delete shapesmembershabnamsarup10 Oct '12 - 8:07 
I have a canvas where the background is set to an image. I need to allow the user to draw rectangles on the image to mask off certain areas. The user has to be able to move, resize and delete the masks (rectangles). I am using the MoveThumb and ResizeThumb approach which works very well. But I cannot figure out how to select and delete a rectangle. Since the IsHitTestVisible property of the rectangle is set to false, I cannot determine in the mouse down if a rectangle is under the mouse point.
AnswerRe: Select and delete shapesmemberschmiddd20 Apr '13 - 6:53 
set the property of IsHitTestVisible dynamically. Generally I suggest using MVVM with WPF so, if you bind the xaml's property to a property of the viewmodel, you can play around with the layer actually getting hit.
 
For the selection part, I added another button-layer with transparent background. Here the adaption of the xaml part, using the thumb's ItemDesignerStyle as basis
 
      <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
          <Control x:Name="RotateDecorator" 
                   Template="{StaticResource RotateDecoratorTemplate}" 
                   Visibility="Collapsed"/>
          <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" 
                       Cursor="SizeAll"/>
          <Control x:Name="ResizeDecorator" 
                   Template="{StaticResource ResizeDecoratorTemplate}" 
                   Visibility="Collapsed"/>
          <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
 
          <!-- This is the invisible Button to allow selection -->
          <Button Background="Transparent" 
                  IsHitTestVisible="{Binding DataContext.SomeProperty,
                      RelativeSource={RelativeSource TemplatedParent}}" 
                  Click="ItemSelected"/>
      </Grid>
 
Now you just have to add the eventhandler "ItemSelected". Bind the ContentControl's Selecter.IsSelected property, where you use the DesignerItemStyle, to another Property of a viewmodel.
 
public void ItemSelected(object sender, RoutedEventArgs e)
{
    ContentControlViewModel.IsSelected =  !ContentControlViewModel.IsSelected;
}
 
As the ViewModel propagates the changes your contentcontrol gets selected and shows the thumbs/adorners activated by the already implemented triggers.
GeneralMy vote of 5memberzzfima9 Oct '12 - 22:13 
very good article
GeneralMy vote of 5memberPeterJerz1 Oct '12 - 1:48 
Very helpful article!
QuestionXAML Resources LookupmemberEdelmeier17 Sep '12 - 23:18 
Hi,
 
When Importing this into one of my applications, I have trouble getting the RotateResizeChrome to be displayed. This goes back to the fact that the style defined in ResizeRotateChrome.xaml is not automatically assigned to instances of the class.
 
I have to first name the style and second add the following code to ResizeRotateAdorner.cs:
 
this.chrome = new ResizeRotateChrome();
this.chrome.Style = FindResource("ExplicitStyleName") as Style;
 
All XAML-Resources are loaded in the same way your code does it (Window loads DesignerItem.xaml, which loads its own requirements). Does anyone have an idea why i need to assign the style explicitly?
 
TIA
GeneralMy vote of 5memberMember 778437717 Sep '12 - 23:08 
Brilliant, Markus Smile | :)
Questionhow to select one item alonememberMember 91736163 Jul '12 - 1:36 
Hi
 
can you help me please,
 
In your example instead of clicking check box, if i click that object that object only should select how? then if i click canvas all no selection will go like your Diagram designer 4
GeneralMy vote of 5memberMadhan Mohan Reddy28 Jun '12 - 21:03 
awesome work man
Questionmy vote of 5memberGreg Cadmes28 Jun '12 - 11:10 
Your examples are perfect! thank you, thank you!
 
One question about the ResizeThumb. If there was a property for Lock Aspect Ratio, can you demonstrate what that might look like?
 
I've struggled with it for awhile now, and can't quite get it.
 
thanks again for the excellent demos
 
Greg
Questionadd a constraint to resize thumbmemberthefox8530 May '12 - 22:18 
I would to resize contentcontrol with aspect ratio.
I don't understand horizontal change and vertical change and their relations. Smile | :)
AnswerRe: add a constraint to resize thumbmemberschmiddd20 Apr '13 - 6:35 
this should not be too difficult. Adapt the resize function a little. Add for each change of height a change of width as well. Notice however, that
item.Width += ratio * deltaVertical;
turns to
item.Height += (1/ratio) * deltaVertical;
for the height adaption.
 

double ratio = item.Width/item.Height;
 
switch (VerticalAlignment)
            {
                case VerticalAlignment.Bottom:
                    deltaVertical = Math.Min(-e.VerticalChange, 
                        item.ActualHeight - item.MinHeight);
                    item.Height -= deltaVertical;
 
                    // the next line preserves the ratio
                    item.Width += ratio * deltaVertical;
 

                    break;

QuestionDynamically implementation.memberronziv17 May '12 - 18:20 
Hi,
 
Thanks for the good article!!!
 
How do I implement dynamically the movable controls ( e.g. add N Ellipses control in the code behind)?
QuestionHow would this work when databinding the ContentControl?memberDavid_Keaveny7 May '12 - 15:21 
This is a very helpful series. I was hoping you might be able to explain how you it would work when the ContentControl is bound to a business object, which has X/Y/Width/Height properties?
 
So if my XAML looked like this:
 
<ContentControl Width="{Binding Width}"
     Height="{Binding Height}"
     Canvas.Top="{Binding Y}"
     Canvas.Left="{Binding X}"
     Style="{StaticResource DesignerItemStyle}"/>
 
then the control renders as expected, but the move/resize thumbs don't work when they call Canvas.SetLeft and Canvas.SetTop. I have modified the MoveThumb and ResizeThumb controls to extract my business object from the ContentControl's DataContext, and set the properties on that, after which the move/resize works again, like this:
 
protected void OnMoveThumbDragDelta(object sender, DragDeltaEventArgs e)
{
    var designerItem = DataContext as ContentControl;
    if (designerItem == null)
    {
        return;
    }
 
    var tableViewModel = designerItem.DataContext as TableViewModel;
    if (tableViewModel == null)
    {
        return;
    }
 
    var dragDelta = new Point(e.HorizontalChange, e.VerticalChange);
    tableViewModel.X += dragDelta.X;
    tableViewModel.Y += dragDelta.Y;
}
 
but now my controls are not reuseable, as they are coupled to my business object.
--
David Keaveny
"Life is like a sewer - what you get out of it depends on what you put into it" - Tom Lehrer

GeneralMy vote of 5memberMember 88888652 May '12 - 4:12 
NICE!
QuestionnicememberCIDev25 Apr '12 - 11:17 
A very nice start on how to do things in WPF.
Just because the code works, it doesn't mean that it is good code.

Question.net 4.0memberfubarrr16 Apr '12 - 3:04 
Hi,
 
I tried to build the project with .net 4.0, but the rotate/resize adorners are no longer visible. Does anyone know what I need to change?
 
thanks.
AnswerRe: .net 4.0memberfubarrr16 Apr '12 - 3:07 
Nevermind, I found the answer in a thread below.
GeneralRe: .net 4.0memberMember 867745820 May '12 - 10:54 
Could you please explain the solution?
I have the same issue and I didn't find the solution yet.
 
Maybe you're referring to [this thread]
 
Could somebody help me with this code in .NET 4.0 ? This code seems really nice.
 
Regards,
GeneralRe: .net 4.0memberPLMorek16 Sep '12 - 0:50 
He meaned this thread:
Solution
I had the same error, so it helped me as well.
Questionstop overlapping...memberajit_mac5 Mar '12 - 3:50 
Dear Reader,
Hi,

I have wrote for button click
System.Windows.Shapes.Ellipse lb = new System.Windows.Shapes.Ellipse();
            lb.IsHitTestVisible = false;
            lb.Name = "dynecp";
            lb.Fill = System.Windows.Media.Brushes.DeepSkyBlue;
            
            System.Windows.Controls.ContentControl contcrl = new System.Windows.Controls.ContentControl();
            contcrl.MinHeight = 35;
            contcrl.MinWidth = 90;
            contcrl.Height = 40;
            contcrl.Width = 120;
            contcrl.Content = lb;
            contcrl.Name = "iamdyn";
         
            Canvas.SetLeft(contcrl, 30);
            Canvas.SetTop(contcrl, 40);
            contcrl.Template = this.Resources["DesignerItemTemplate"] as ControlTemplate;
            contcrl.ApplyTemplate();
            tes1t.Children.Add(contcrl);
 
what i want is the generated controls should not overlap on each other...when i move them
 
please help...
Questionplease help ............dynamically adding control over canvas [modified]memberajit_mac20 Feb '12 - 7:22 
private void button1_Click(object sender, RoutedEventArgs e)
{
//System.Windows.Controls.Label lb = new System.Windows.Controls.Label();
//lb.Content = "this is test lable";
//lb.IsHitTestVisible = false;
 
System.Windows.Shapes.Ellipse lb = new System.Windows.Shapes.Ellipse();
lb.IsHitTestVisible = false;
lb.Name = "dynecp";
lb.Fill = System.Windows.Media.Brushes.DeepSkyBlue;

System.Windows.Controls.ContentControl contcrl = new System.Windows.Controls.ContentControl();
contcrl.MinHeight = 35;
contcrl.MinWidth = 90;
contcrl.Height = 40;
contcrl.Width = 120;
contcrl.Content = lb;
contcrl.Name = "iamdyn";

contcrl.Template = this.Resources["DesignerItemTemplate"] as ControlTemplate;
contcrl.ApplyTemplate();
//contcrl.Margin = new System.Windows.Thickness(10, 10, 0, 0);

tes1t.Children.Add(contcrl);

}
 

 
I have added control successfully.... and i can even resize it..
 
but please help me to move the control round the canvas.
 
thanks a lot

modified 21 Feb '12 - 13:01.

AnswerRe: please help ............dynamically adding control over canvasmemberramsayra28 Feb '12 - 6:47 
can u send me a full sample of your code ?
 
thank u
GeneralRe: please help ............dynamically adding control over canvasmemberajit_mac29 Feb '12 - 9:07 
Dear Ramsayra,
 
Thanks for looking into it but i have found solution to that problem...
 
still if you want to know the code
 

System.Windows.Shapes.Ellipse lb = new System.Windows.Shapes.Ellipse();
            lb.IsHitTestVisible = false;
            lb.Name = "dynecp";
            lb.Fill = System.Windows.Media.Brushes.DeepSkyBlue;
            
            System.Windows.Controls.ContentControl contcrl = new System.Windows.Controls.ContentControl();
            contcrl.MinHeight = 35;
            contcrl.MinWidth = 90;
            contcrl.Height = 40;
            contcrl.Width = 120;
            contcrl.Content = lb;
            contcrl.Name = "iamdyn";
         
            Canvas.SetLeft(contcrl, 30);
            Canvas.SetTop(contcrl, 40);
            contcrl.Template = this.Resources["DesignerItemTemplate"] as ControlTemplate;
            contcrl.ApplyTemplate();
            tes1t.Children.Add(contcrl);
 
Thank you
Questionhow can i stop overlapping ??memberajit_mac10 Feb '12 - 1:40 
Hi friends,
 
could anyone of you help me to stop overlapping the moving objects ?
D'Oh! | :doh: Confused | :confused:
QuestionAdd scale transform in addition to Height / Width modification?memberSimon Mansfield26 Jan '12 - 4:16 
Any tips on how one might go about adding scale control if, for example, the Left Control key is held and the resize controls are used? I've got it working to a point, but any "flips" cause it to go haywire; getting a sudden massively positive DragDeltaEventArgs.VerticalDelta when up until then, it's always been negative!?
GeneralMy vote of 5memberFlorian.Witteler18 Jan '12 - 12:23 
Excellent article and VERY impressive demo of WPF's capabilities. Trying to understand everything now...
 
Thanks for sharing
GeneralMy Vote of 5memberRaviRanjankr16 Oct '11 - 10:56 
Interesting article. Thumbs Up | :thumbsup:
Questionremoving selectormemberMember 81683008 Sep '11 - 5:00 
I am trying to remove the selector from the content control like the one executed in the adorner example. I cant seem to do it. Any idea how you can do that. Remove the selector from the content control in the thumb example.
QuestionIs there any who update this project to restrict move and resize ?memberDorian PIERRE20 Jul '11 - 6:13 
I looking for restricted version that not allow to go out of the contenair ...
Thanks a lot
Dorian
Questionexplainmemberbocheli9 Jul '11 - 10:23 
Hoi,
 
Are you willing to give me a more detailed explanation if i pay ?
 
Regards
GeneralMy vote of 5membersalim4187 Jul '11 - 1:38 
you save me man!! thanks a ton... keep it up...
Generalexplainingmemberbocheli6 Jun '11 - 4:31 
Astonishing project!! Just one question. Do you have a more detailed explanation for a wpf/c# beginner?
GeneralMy vote of 5memberFishbox19 Mar '11 - 9:37 
Explains some great control functions in an easy-to-follow article!
Generalhey man I would like to ask you somethingmvpSacha Barber19 Mar '11 - 0:21 
A while back I built this tool in WinForms : 100% Reflective Class Diagram Creation Tool[^] which was pretty popular.
 
I have been thinking about bringing it up to date using WPF lately, and could think of no better way to do the layout then to use you fine work, and was wondering when the time is right whether you might be interested in giving me a small helping hand?
 
I could do it by myself based on these excellent articles of yours, just wondering if you may be interested is all.
Sacha Barber
  • Microsoft Visual C# MVP 2008-2011
  • Codeproject MVP 2008-2011
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralGreat ArticlememberJCox_Prog6 Feb '11 - 3:57 
I have been searching for examples on this topic on and off and just found this one. It shows all they key points in one place.
 
Thanks.
GeneralMy vote of 5memberJCox_Prog6 Feb '11 - 3:54 
Well written and concise examples
GeneralMy vote of 5membermao_kun11 Dec '10 - 20:08 
It's very good!
QuestionGreat article, VB version?memberHagayMandel20 Nov '10 - 9:57 
Is it possible to get a VB version?
Hagay Mandel

GeneralMy vote of 5memberVermaManish18 Nov '10 - 23:02 
My vote of 5
GeneralMy vote of 5memberIrishRover15 Nov '10 - 9:18 
Really clear & useful article!
GeneralMy vote of 5membersuryawang24 Oct '10 - 17:24 
very good article for make designer application
GeneralMy vote of 5memberVirtualVoid.NET11 Oct '10 - 21:58 
this is GREAT Smile | :)
GeneralMy vote of 5memberPat Kujawa17 Sep '10 - 5:02 
Thoroughly documented and a well-informed solution.
QuestionHow rotate cursor direction when resize the control?membergo2sleep3 Sep '10 - 17:08 
First rotated control, when resize the control, How rotate cursor as control's Angle?
Thank you Smile | :)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 24 Aug 2008
Article Copyright 2008 by sukram
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid