Show labels on DesignerItems

The WPF Diagram Designer does not have the ability to show labels on the DesignerItems. In this tutorial we will not only cover how to set simple labels on the DesignerItems, but also give the user the possibility to enter text right on DesignerItem itself.

Here are some screenshots of what you’ll get when you implemented it.

WPF Diagram Designer - DesignerItem with label in edit-mode
WPF Diagram Designer - DesignerItem with label

 

How exactly can the user edit the labels in the DesignerItem?

We’ll implement it so, that if he selects the DesignerItem and clicks on the DesignerItem again within one second, then the DesignerItem switches to the edit-mode and lets the user change the label. If he then deselects the DesignerItem, it will revert from the edit-mode to only showing the label again.

Setting up the necessary properties on DesignerItem

To enable showing labels, we need to have properties to store the label and we need to now, in which mode we currently are.

  1. Open the file DesignerItem.cs
  2. Search for static DesignerItem(). Right above it, copy the following code:
    #region ItemLabel
    
    public string ItemLabel
    {
        get { return (string)GetValue(ItemLabelProperty); }
        set { SetValue(ItemLabelProperty, value); }
    }
    public static readonly DependencyProperty ItemLabelProperty =
        DependencyProperty.Register("ItemLabel",
                                    typeof(string),
                                    typeof(DesignerItem),
                                    new FrameworkPropertyMetadata("test"));
    #endregion
    
    #region IsLabelInEditMode
    
    public bool IsLabelInEditMode
    {
        get { return (bool)GetValue(IsLabelInEditModeProperty); }
        set { SetValue(IsLabelInEditModeProperty, value); }
    }
    public static readonly DependencyProperty IsLabelInEditModeProperty =
        DependencyProperty.Register("IsLabelInEditMode",
                                    typeof(bool),
                                    typeof(DesignerItem),
                                    new FrameworkPropertyMetadata(false));
    
    #endregion
    

Displaying the label and the edit-textbox

To show and edit the label on the DesignerItem, we need to add a label and a textbox in the DesignerItem.xaml

  1. Open the file DesignerItem.xaml
  2. Search for x:Name=”PART_ConnectorDecorator”. Right below this control paste the following code:
    <TextBox x:Name="itemEditLabelTextbox" Text="{Binding Path=ItemLabel, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource TemplatedParent}}" Margin="5 0 5 0" VerticalAlignment="Center" />
    <Label x:Name="itemLabel" Content="{Binding Path=ItemLabel, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    
  3. Right now the controls are bound to our properties, but we also need to say them, when they need to show up. We’ll use a WPF DataTrigger to do so. Right below the textbox and the label you can see the element <ControlTemplate.Triggers>. Inside it paste the following code:
    <DataTrigger Value="False" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsLabelInEditMode}">
        <Setter TargetName="itemEditLabelTextbox" Property="Visibility" Value="Hidden"/>
        <Setter TargetName="itemLabel" Property="Visibility" Value="Visible"/>
    </DataTrigger>
    <DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsLabelInEditMode}">
        <Setter TargetName="itemEditLabelTextbox" Property="Visibility" Value="Visible"/>
        <Setter TargetName="itemLabel" Property="Visibility" Value="Hidden"/>
    </DataTrigger>
    

    As you can see, depending on if IsLabelInEditMode is true or false, either the label or the textbox is shown.

Setting up a timer for edit-mode

The tutorial here uses a timer to enter the editmode. If you would like another way to enter the editmode, just provide a possibility to set IsLabelInEditMode either to true or false. To explain the trick with the timer shortly – we’ll use a timer to check, if the timer has elapsed within 1500ms, before a next click comes. If the click comes, we’ll set the DesignerItem to the edit-mode.

  1. First open the file DesignerItem.cs
  2. Add the following members to the DesignerItem-class:
    // In the original DesignerItem-class designerCanvas is grabbed locally in the OnPreviewMouseDown-Method. As we need it in the OnPreviewMouseDown- and the designerCanvas_PreviewMouseUp-Method, we store it once within the constructor.
    private DesignerCanvas designer = null;
    
    // The editModeTimer is used to measure, if the 1500 milliseconds have elapsed.
    private System.Timers.Timer editModeTimer = new System.Timers.Timer(1500);
    
    // The selectedClickCounter is used to check, if a second time has been clicked on the DesignerItem.
    private int selectedClickCounter = 0;
    
  3. Search the constructor public DesignerItem(Guid id) and add the following line in it:
    editModeTimer.Elapsed += editModeTimer_Elapsed;
    

    Right below the constructor add the method editModeTimer_Elapsed:

    // When the timer is elapsed, the counter will be reverted to zero and the timer stopped
    void editModeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        selectedClickCounter = 0;
        editModeTimer.Stop();
    }
    
  4. In the function OnPreviewMouseDown remove the following code. We’ll set the designer-variable in the next step in the DesignerItem_Loaded-method.
    DesignerCanvas designer = VisualTreeHelper.GetParent(this) as DesignerCanvas;
    
  5. Right at the beginning of the DesignerItem_Loaded-method add the following
    if(this.designer == null)
    {
      designer = VisualTreeHelper.GetParent(this) as DesignerCanvas;
      designer.PreviewMouseUp += designerCanvas_PreviewMouseUp;
    }
    
  6. Add the following code to the DesignerItem
    void designerCanvas_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
      if(this.IsSelected)
      {
        if(editModeTimer.Enabled == false)
        {
          editModeTimer.Start();
        }
        selectedClickCounter++;
        if(selectedClickCounter == 2)
        {
          this.IsLabelInEditMode = true;
        }
      }
      else
      {
        selectedClickCounter = 0;
        this.IsLabelInEditMode = false;
      }
    }