Click here to Skip to main content
15,880,469 members
Articles / Desktop Programming / WPF
Alternative
Article

Custom TreeView Layout in WPF

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
12 Sep 2014CPOL2 min read 26.3K   19   7
This is an alternative for "Custom TreeView Layout in WPF"

Introduction

I needed to draw lines between the nodes and collapsing/expanding of the nodes. Turned out that collapsing/expanding was very easy to implement.

Drawing lines was a bit more difficult.

The solution works perfect but I’m sure there is a simpler approach to this problem. Anyway, if someone needs a solution, this one works.

The treeview:

Image 1

Using the Code

Below is the ControlTemplate.

There are 3 rows in the first Grid.

  • The first one is for the horizontal line(s).
  • the second one for the UserControl.
  • The last one holds the ItemsPresenter.
XML
<ControlTemplate TargetType="TreeViewItem">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Grid Grid.Row="0">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <Line Grid.Column="0" SnapsToDevicePixels="True" 
                                    Visibility="{Binding  ., UpdateSourceTrigger=PropertyChanged, 
                                    Converter={c:IsFlowElementFrom_ToLeftLineVisiblility_Converter}}" 
                                    Grid.Row="0" HorizontalAlignment="Stretch" 
                                    VerticalAlignment="Bottom" Stroke="Black" 
                                    X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" 
                                    StrokeThickness="2" />
                                    <Line Grid.Column="1" SnapsToDevicePixels="True" 
                                    Visibility="{Binding  ., UpdateSourceTrigger=PropertyChanged, 
                                    Converter={c:IsFlowElementFrom_ToRigthLineVisiblility_Converter}}" 
                                    Grid.Row="0" HorizontalAlignment="Stretch" 
                                    VerticalAlignment="Bottom" Stroke="Black" 
                                    X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" 
                                    StrokeThickness="2" />
                                </Grid>
                                <StackPanel Grid.Row="1" Orientation="Vertical" 
                                HorizontalAlignment="Center">
                                    <f:FlowElementControl FlowElementControl_IsReported_Event=
                                    "FlowElementControl_FlowElementControl_IsReported_Event" 
                                                          FlowElementControl_IsSelected_Event=
                                                          "FlowElementControl_IsSelected_Event"  
                                                          ButtonExpand_ClickEvent=
                                                          "FlowElementControl_ButtonExpand_ClickEvent"  
                                                          ButtonExtraInfo_ClickEvent=
                                                          "FlowElementControl_ButtonExtraInfo_ClickEvent" 
                                                          FlowElementControl_IsUserResponse_Event=
                                                          "FlowElementControl_FlowElementControl_IsUserResponse_Event"
                                                          Visibility="{Binding  .FlowElementFrom.TreeviewItem_IsExpanded, 
                                                          UpdateSourceTrigger=PropertyChanged, 
                                                          Converter={c:IsParentExpandedToVisibility_Converter}}" 
                                                          Tag="{Binding .}"  
                                                          HorizontalAlignment="Center">
                                    </f:FlowElementControl>
                                </StackPanel>
                                <ItemsPresenter Grid.Row="2">
                                </ItemsPresenter>
                            </Grid>
                        </ControlTemplate>

The horizontal line between the nodes are actually two lines. They are both the half length of the first Grid. To do this, we place a new Grid in the first row and give this Grid 2 equally spaced columns (1*) (the width of the first Grid changes according to the nodes below them, so cannot use a fixed width of the lines).

We need two lines in order to hide or show them accordingly to the position of the nodes.

  • If the node is the most left one, we hide the left line. (TreeviewItem_IsFirst = true)
  • If the node is the most right one, we hide right line. (TreeviewItem_IsLast = true)
  • If the node is neither the most left or right, we show both lines. (TreeviewItem_IsFirst = false, TreeviewItem_IsLast = false)

The first and last nodes are set in the database.

Image 2

C#
SetFirstAndLast()

We have to do this everytime we add, delete, copy or move items.

You can add a sort order if needed.

C#
        private void RecursiveSetFirstLast(Database.FlowElements flowelement)
        {
            List<Database.FlowElements> toList = flowelement.FlowElementsTo.ToList();
            for (int i = 0; i < toList.Count; i++)
            {
                if (i == 0)
                    toList[i].TreeviewItem_IsFirst = true;
                else
                    toList[i].TreeviewItem_IsFirst = false;

                if (i == toList.Count - 1)
                    toList[i].TreeviewItem_IsLast = true;
                else
                    toList[i].TreeviewItem_IsLast = false;

                if (i != 0 & i != toList.Count - 1)
                {
                    toList[i].TreeviewItem_IsFirst = false;
                    toList[i].TreeviewItem_IsLast = false;
                }
                RecursiveSetFirstLast(toList[i]);
            }
        }
        private void SetFirstAndLast()
        {
            //set first and last, so we can draw the treelines properly
            foreach (Database.FlowElements f in flowElementsNotLinked) RecursiveSetFirstLast(f);
        }
flowElementsNotLinked = Currenttemplate.FlowElements.Where(f => f.FlowElementFrom == null).ToList();

Next, we need to set the visibility of the lines. This can be done with a converter: (You need two of them, left and right)

C#
class IsFlowElementFrom_ToLeftLineVisiblility_Converter : System.Windows.Markup.MarkupExtension, IValueConverter
    {
        public IsFlowElementFrom_ToLeftLineVisiblility_Converter()
        {

        }
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Database.FlowElements flowelement = (Database.FlowElements)value;
            //do not show the line if there are no elements above
            if (flowelement == null || flowelement.FlowElementFrom == null) return Visibility.Hidden;
            //don't show the left line if it is the first element
            if (flowelement.TreeviewItem_IsFirst) return Visibility.Hidden;
            return Visibility.Visible;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return true;
        }
        private static IsFlowElementFrom_ToLeftLineVisiblility_Converter instance;
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (instance == null)
                instance = new IsFlowElementFrom_ToLeftLineVisiblility_Converter();
            return instance;
        }
    }

Last thing to do is draw two short vertical lines in your usercontrol (top and bottom). And show/hide them based on the elements above or below them. You can use the same principle as above.

Best to replace the bottom line of the control with a menuItem or button with a plus or minus in it. For collapsing and expanding.

XML
<Menu Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center">
                <MenuItem x:Name="ButtonExpand" Tag="{Binding .}" Visibility="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:FlowelementsTo_ToButtonVisiblility_Converter}}" IsEnabled="True" Click="ButtonExpand_Click">
                    <MenuItem.Header>
                        <TextBlock FontSize="12" Text="{Binding  ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsExpandedToTextBlockText_Converter}}" xml:space="preserve"></TextBlock>
                    </MenuItem.Header>
                    <MenuItem.Effect>
                        <DropShadowEffect Opacity="0.5" ShadowDepth="4" BlurRadius="8"/>
                    </MenuItem.Effect>
                    <MenuItem.ToolTip>
                        <TextBlock>
                              Collapse/Expand this flowelement.
                        </TextBlock>
                    </MenuItem.ToolTip>
                </MenuItem>
            </Menu>

Image 3

Points of Interest

I tried some very different approaches, this was the first one that worked. Next try would have been just drawing on the canvas.

During testing, I gave all containers a different color and margin. This shows you what is actually happing and can be very helpful.

History

  • 12th September, 2014: Initial version

License

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


Written By
Software Developer (Senior)
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionEmergency Pin
Harun Taşdemir18-Jul-20 1:04
Harun Taşdemir18-Jul-20 1:04 
QuestionFull source Pin
User 1088693326-Mar-15 23:51
User 1088693326-Mar-15 23:51 
AnswerRe: Full source Pin
Jan Bakker27-Mar-15 0:14
Jan Bakker27-Mar-15 0:14 
I can't give you the entire code, it's huge and specific to my needs.
And My boss would not like that Smile | :)
I can give the code for FlowElementControl, but it is just a usercontrol. You should use your own usercontrol.

FlowElementControl

XML
<UserControl x:Class="Industrialisatie_proces.Flowelement.FlowElementControl"
             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" 
             xmlns:c="clr-namespace:Industrialisatie_proces"
             Background="White" Width="150" Height="239" Focusable="True"
             VirtualizingPanel.IsVirtualizing="True">
    <Canvas>
        <Canvas.Resources>
            <Style TargetType="MenuItem">
                <Setter Property="Tag" Value="{Binding Id}"/>
                <Setter Property="Width" Value="35"/>
                <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
                <Setter Property="FontSize" Value="18"/>
            </Style>
        </Canvas.Resources>
        <Line Visibility="{Binding .FlowElementFrom, UpdateSourceTrigger=PropertyChanged, Converter={c:IsFlowElementFrom_ToLineVisiblility_Converter}}" SnapsToDevicePixels="True" X1="74" X2="74" Y1="-2" Y2="8" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center"></Line>
        <Border Margin="4,8,0,0" Width="141" Height="210" Name="BorderFlowElement" CornerRadius="10" BorderThickness="2" BorderBrush="{Binding .TreeviewItem_IsSelected, UpdateSourceTrigger=PropertyChanged, Converter={c:Selected_ToBorderBrush_Converter}}" Background="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:FlowElementBackGroundToUserDecision}}"/>
        <Border Name="BorderAswer" Margin="13,16,0,0" Width="124" Height="72" CornerRadius="6"  Background="Navy" HorizontalAlignment="Center"/>
        <TextBox Tag="{Binding .}"
                 Margin="16,22,0,0"
                 Text="{Binding FlowElementTextFrom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                 Height="60" 
                 IsReadOnly="{Binding UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_Convertor}}" 
                 CaretBrush="Orange" 
                 PreviewMouseLeftButtonUp="TextBoxAswer_PreviewMouseLeftButtonUp"
                 Name="TextBoxAswer" 
                 KeyUp="TextBoxAswer_KeyUp"
                 MaxLength="25" 
                 HorizontalContentAlignment="Center" 
                 FontSize="18" 
                 Foreground="Orange" 
                 Background="Navy"
                 BorderThickness="0" 
                 VerticalContentAlignment="Center" 
                 Width="118" 
                 VerticalAlignment="Center" 
                 HorizontalAlignment="Center" 
                 TextWrapping="Wrap" 
                 ></TextBox>
        <TextBox Tag="{Binding .}" 
                             Text="{Binding FlowElementText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                 Margin="14,90,0,0"
                             Name="TextBoxFlowText" 
                             MaxLength="100" 
                             KeyUp="TextBoxFlowText_KeyUp"
                             Loaded="TextBoxFlowText_Loaded"
                             IsReadOnly="{Binding UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_Convertor}}"
                             BorderThickness="0" 
                             Background="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:FlowElementBackGroundToUserDecision}}" 
                             Width="122" 
                             PreviewMouseLeftButtonUp="TextBoxFlowText_PreviewMouseLeftButtonUp" 
                             Height="90" 
                             TextWrapping="Wrap" 
                             FontSize="12" 
                             AcceptsReturn="True" 
                             AcceptsTab="True" 
                             AutoWordSelection="True" 
                             HorizontalAlignment="Center" 
                             />
        <Menu Name="StackPanelUserResponse" Visibility="Collapsed" Margin="38,120,0,0" Background="Orange">
            <Menu.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Vertical"/>
                </ItemsPanelTemplate>
            </Menu.ItemsPanel>
            <MenuItem x:Name="ButtonUserResponseText" 
                              Tag="{Binding .}" 
                              Foreground="{Binding .IsUserResponseTextRequired, UpdateSourceTrigger=PropertyChanged, Converter={c:IsUserTextResponsToColor_Converter}}" 
                              Click="ButtonUserResponseText_Click">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                 The user <Underline>must</Underline> enter a text!
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
            <MenuItem x:Name="ButtonUserResponseDocument" 
                              Tag="{Binding .}" 
                              Foreground="{Binding .IsUserResponseDocumentRequired, UpdateSourceTrigger=PropertyChanged, Converter={c:IsUserDocumentResponsToColor_Converter}}" 
                              Click="ButtonUserResponseDocument_Click">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                 The user <Underline>must</Underline> provide a document!
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
        </Menu>

        <Menu Name="StackPanelReportingText" Visibility="Collapsed" Margin="90,150,0,0" Background="Orange">
            <MenuItem x:Name="ButtonReportingText" 
                      Tag="{Binding .}" 
                      Foreground="Black" 
                      Click="ButtonReportingText_Click"
                      MouseLeave="ButtonReportingText_MouseLeave"
                      MouseEnter="ButtonReportingText_MouseEnter">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                 The text that apears on the report.
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
        </Menu>

        <Menu Margin="2,180,0,7" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" Background="Transparent" HorizontalAlignment="Center">
            <MenuItem x:Name="ButtonExtraInfo" 
                                      Tag="{Binding .}" 
                                      Foreground="{Binding .extraInfo, UpdateSourceTrigger=PropertyChanged, Converter={c:ExtraInfoToColor_Converter}}" 
                                      Visibility="{Binding .extraInfo, UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_ToExtraVisiblility_Converter}}"
                                      Click="ButtonExtraInfo_Click">
                <MenuItem.Header>
                    <TextBlock xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                        Some extra Info.
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
            <MenuItem x:Name="ButtonUserResponse" Tag="{Binding .}"
                                      Foreground="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsUserResponsToColor_Converter}}" 
                                      Visibility="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_ToButtonVisiblility_Converter}}" 
                                      Click="ButtonUserResponse_Click">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                         The user must enter a respons.
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
            <MenuItem x:Name="ButtonIsMarkedAsSolved" 
                       Tag="{Binding .}" 
                       Foreground="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsMarkedSolved_ToColor_Converter}}" 
                       Visibility="{Binding UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_ToButtonVisiblility_Converter}}"
                       Click="ButtonIsMarkedAsSolved_Click"
                       MouseEnter="ButtonIsMarkedAsSolved_MouseEnter"
                       MouseLeave="ButtonIsMarkedAsSolved_MouseLeave">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                           Report as solved.
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
  
            <MenuItem x:Name="ButtonIsMarkedProblem" 
                       Tag="{Binding .}" 
                       Foreground="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsMarkedAsProblem_ToColor_Converter}}" 
                       Visibility="{Binding UpdateSourceTrigger=PropertyChanged, Converter={c:IsReadOnly_ToButtonVisiblility_Converter}}"
                       Click="ButtonIsMarkedProblem_Click"
                       MouseEnter="ButtonIsMarkedAsSolved_MouseEnter"
                       MouseLeave="ButtonIsMarkedAsSolved_MouseLeave">
                <MenuItem.Header>
                    <TextBlock Text="" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                                          Report as problem.
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
        </Menu>
        <Menu Margin="55,219,0,0" VirtualizingPanel.IsVirtualizing="True" HorizontalContentAlignment="Center" VirtualizingPanel.VirtualizationMode="Recycling" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center">
            <MenuItem x:Name="ButtonExpand" Tag="{Binding .}" Visibility="{Binding ., UpdateSourceTrigger=PropertyChanged, Converter={c:FlowelementsTo_ToButtonVisiblility_Converter}}" IsEnabled="True" Click="ButtonExpand_Click">
                <MenuItem.Header>
                    <TextBlock FontSize="12" Text="{Binding  ., UpdateSourceTrigger=PropertyChanged, Converter={c:IsExpandedToTextBlockText_Converter}}" xml:space="preserve"></TextBlock>
                </MenuItem.Header>
                <MenuItem.ToolTip>
                    <TextBlock>
                              Collapse/Expand this flowelement. <LineBreak/>(Use Ctrl for all expand/collapse)
                    </TextBlock>
                </MenuItem.ToolTip>
            </MenuItem>
        </Menu>
    </Canvas>
</UserControl>


C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;

namespace Industrialisatie_proces.Flowelement
{
	/// <summary>
	/// Interaction logic for FlowElementxaml.xaml
	/// </summary>
	public partial class FlowElementControl : UserControl
    {
        DispatcherTimer TimerButtonReportingText = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };
        public FlowElementControl()
        {
            InitializeComponent();
            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.VerticalAlignment = VerticalAlignment.Top;
            TimerButtonReportingText.Tick += TimerButtonReportingText_Tick;
        }

        #region events
        private void TextBoxFlowText_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //select this usercontrol and focus TextBoxFlowText
            SelectFlowControl(sender, false);
        }
        private void TextBoxAswer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //select this usercontrol and do not focus TextBoxAswer
            SelectFlowControl(sender, true);
        }
        private void TextBoxFlowText_Loaded(object sender, RoutedEventArgs e)
        {
            Database.FlowElements flowElement = (Database.FlowElements)((TextBox)TextBoxFlowText).Tag;
            if (flowElement == null || !flowElement.TreeviewItem_IsSelected || flowElement.TreeviewItem_InitialFocusIsSet) return;
            {
                flowElement.TreeviewItem_InitialFocusIsSet = true;
                TextBoxFlowText.Focus();
                TextBoxFlowText.CaretIndex = TextBoxFlowText.Text.Length;
            }
        }
        private void ButtonExtraInfo_Click(object sender, RoutedEventArgs e)
        {
            ButtonExtraInfo_ClickEvent(this);
        }
        private void ButtonExpand_Click(object sender, RoutedEventArgs e)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
                ButtonControlExpand_ClickEvent(this);
            else
                ButtonExpand_ClickEvent(this);
        }
        private void ButtonIsMarkedAsSolved_Click(object sender, RoutedEventArgs e)
        {
            FlowElementControl_IsMarkedSolved_Event((Database.FlowElements)((MenuItem)sender).Tag);
        }
        private void ButtonIsMarkedProblem_Click(object sender, RoutedEventArgs e)
        {
            FlowElementControl_IsMarkedProblem_Event((Database.FlowElements)((MenuItem)sender).Tag);
        }
        private void ButtonUserResponseDocument_Click(object sender, RoutedEventArgs e)
        {
            StackPanelUserResponse.Visibility = Visibility.Collapsed;
            FlowElementControl_IsUserDocumentResponse_Event((Database.FlowElements)((MenuItem)sender).Tag);
        }
        private void ButtonUserResponseText_Click(object sender, RoutedEventArgs e)
        {
            StackPanelUserResponse.Visibility = Visibility.Collapsed;
            FlowElementControl_IsUserTextResponse_Event((Database.FlowElements)((MenuItem)sender).Tag);
        }
        private void ButtonUserResponse_Click(object sender, RoutedEventArgs e)
        {
            StackPanelUserResponse.Visibility = StackPanelUserResponse.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        }
        private void ButtonReportingText_Click(object sender, RoutedEventArgs e)
        {
            ButtonReportingText_ClickEvent((Database.FlowElements)((MenuItem)sender).Tag);
        }
        private void TextBoxAswer_KeyUp(object sender, KeyEventArgs e)
        {
            //prevent bubbling to WindowBuiltTemplate
            e.Handled = true;
            if (e.Key == Key.Escape)
                this.Focus();
            //if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.X && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.Delete) e.Handled = true;
        }
        private void TextBoxFlowText_KeyUp(object sender, KeyEventArgs e)
        {
            //prevent bubbling to WindowBuiltTemplate
            e.Handled = true;
            if (e.Key == Key.Escape)
                this.Focus();
            //if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.X && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control) e.Handled = true;
            //if (e.Key == Key.Delete) e.Handled = true;
        }
        #region custom events
        public delegate void ButtonExtraInfo_Click_Handler(FlowElementControl flowElementControl);
        public event ButtonExtraInfo_Click_Handler ButtonExtraInfo_ClickEvent = delegate { };

        public delegate void ButtonExpand_Click_Handler(FlowElementControl flowElementControl);
        public event ButtonExpand_Click_Handler ButtonExpand_ClickEvent = delegate { };

        public delegate void ButtonControlExpand_Click_Handler(FlowElementControl flowElementControl);
        public event ButtonControlExpand_Click_Handler ButtonControlExpand_ClickEvent = delegate { };

        public delegate void FlowElementControl_IsSelected_Handler(Database.FlowElements flowElement, FlowElementControl flowElementControl);
        public event FlowElementControl_IsSelected_Handler FlowElementControl_IsSelected_Event = delegate { };

        public delegate void FlowElementControl_IsMarkedProblem_Handler(Database.FlowElements flowElement);
        public event FlowElementControl_IsMarkedProblem_Handler FlowElementControl_IsMarkedProblem_Event = delegate { };

        public delegate void FlowElementControl_IsMarkedSolved_Handler(Database.FlowElements flowElement);
        public event FlowElementControl_IsMarkedSolved_Handler FlowElementControl_IsMarkedSolved_Event = delegate { };

        public delegate void FlowElementControl_IsUserTextResponse_Handler(Database.FlowElements flowElement);
        public event FlowElementControl_IsUserTextResponse_Handler FlowElementControl_IsUserTextResponse_Event = delegate { };

        public delegate void FlowElementControl_IsUserDocumentResponse_Handler(Database.FlowElements flowElement);
        public event FlowElementControl_IsUserDocumentResponse_Handler FlowElementControl_IsUserDocumentResponse_Event = delegate { };

        public delegate void ButtonReportingText_Click_Handler(Database.FlowElements flowElement);
        public event ButtonReportingText_Click_Handler ButtonReportingText_ClickEvent = delegate { };
        #endregion

        private void SelectFlowControl(object sender, bool initialFocusIsSet)
        {
            Database.FlowElements flowElement = (Database.FlowElements)((TextBox)sender).Tag;
            if (flowElement == null) return;
            if (!flowElement.TreeviewItem_IsSelected)
            {
                flowElement.TreeviewItem_InitialFocusIsSet = initialFocusIsSet;
                FlowElementControl_IsSelected_Event(flowElement, this);
            }
        }
        private void ButtonIsMarkedAsSolved_MouseEnter(object sender, MouseEventArgs e)
        {
            StackPanelReportingText.Visibility = Visibility.Visible;
        }
        private void ButtonIsMarkedAsSolved_MouseLeave(object sender, MouseEventArgs e)
        {
            TimerButtonReportingText.Start();
        }
        void TimerButtonReportingText_Tick(object sender, EventArgs e)
        {
            TimerButtonReportingText.Stop();
            StackPanelReportingText.Visibility = Visibility.Collapsed;
        }
        private void ButtonReportingText_MouseLeave(object sender, MouseEventArgs e)
        {
            StackPanelReportingText.Visibility = Visibility.Collapsed;
        }
        private void ButtonReportingText_MouseEnter(object sender, MouseEventArgs e)
        {
            TimerButtonReportingText.Stop();
        }
        #endregion
    }
}

GeneralRe: Full source Pin
Jan Bakker27-Mar-15 0:25
Jan Bakker27-Mar-15 0:25 
QuestionNot an article Pin
Akhil Mittal15-Sep-14 19:27
professionalAkhil Mittal15-Sep-14 19:27 
AnswerRe: Not an article Pin
Jan Bakker16-Sep-14 0:48
Jan Bakker16-Sep-14 0:48 
QuestionHave you consider Pin
Nelek15-Sep-14 12:16
protectorNelek15-Sep-14 12:16 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.