Introduction
I present you a control that can be used to link items of two listview
s.
This control helps to link easily listview
items, dragging an item from a listview
to the other or selecting an item in a listview
and right-clicking on an item of the other listview
.
It has by default two listview
s that can be replaced by your own listview
s (for example, if you have an extended listview
).
Links between an item selected in a listview
and items of the other listview
can be displayed with connection lines, rectangles drawn around selected and linked items and rectangle drawn on top of selected and links items.
Background
I had to create it because I needed to link objects of a list to objects of another list through listview
s.
My objects were stored in each listview
item's Tag
property.
I added many features to adapt the interface and the behavior of the control.
Here are screenshots to show how it works.
In my control, I want to create a new link between an item from the left listview
and an item from the right listview
.
I drag the left item over the expected right item:
When I release the item (drop it on the other right item), the control shows me that the link is created:
I then want to link the same item to another right item:
When I drop the item on this new right item, the control shows me that the link is effective:
If I select a right item that was linked, the control shows me its links:
Here, selecting the other right item previously linked:
To remove the link of the left item with a right item, I can drag and drop the left item on the right item already linked. The control shows that the link is about to be removed:
After dropping the item to remove the link, the control updates the view and doesn't display anymore the removed link:
If I select the right item, the control effectively shows that it is not anymore linked with a left item:
In the code, left items are specified with only one link. If I try to link the left item 1 - which is linked to the right item 5 - with the right item 2, the control shows that the link with the right item 5 is about to be removed:
If I confirm the operation, dropping the item, the link is effectively removed:
Now, if I try to link the right item 1 to the left item 1, the control shows that the left item 1 is about to lose its link with the right item 2:
I can adapt the control to prevent display connection lines:
I can adapt the control to prevent displaying rectangles borders:
I can finally adapt the control to prevent filling items with a rectangle:
Using the Code
The control use to link items between each listview
's objects of the ListViewLinkerItemLinks
class.
These objects hold a concerned item of a listview
and all items of the other listview
linked with it.
The control manages two dictionaries of these objects so links can be retrieved for each listview
.
The control can be added to a form or another control and after that, listview
s can be replaced to use custom listview
s:
Form myForm = new Form();
ListViewsLinkerControl listViewsLinkerControl = new ListViewsLinkerControl();
myForm.Controls.Add(listViewsLinkerControl);
ListView leftListView = new ListView();
ListView rightListView= new ListView();
listViewsLinkerControl.LeftListView = leftListView;
listViewsLinkerControl.RightListView = RightListView;
The control provides 4 events:
BeforeItemsLinked
: Fired before two items are linked together. The hosting application can cancel the operation returning the false
value.
BeforeItemsUnlinked
: Fired before two items are unlinked. The hosting application can cancel the operation returning the false
value.
ItemsLinked
: Fired when two items are linked together.
ItemsUnlinked
: Fired when two items are unlinked.
The control provides properties to adapt the user interface:
bool CanLinkFromLeftToRight
: Flag indicating if the user can link an item from the left listview
to items from the right listview
.
bool CanLinkFromRightToLeft
: Flag indicating if the user can link an item from the right listview
to items from the left listview
.
bool OnlyOneLinkForLeftItems
: Flag indicating if items of the left listview
can accept only one link with items of the right listview
.
bool OnlyOneLinkForRightItems
: Flag indicating if items of the left listview
can accept only one link with items of the right listview
.
bool ThrowExceptionIfOperationNotAllowed
: Specify if an exception should be thrown when linking or unlinking two items and operation is not allowed according to the result of "BeforeItemsLinked
" and "BeforeItemsUnlinked
" events.
bool DrawConnectionLines
: Flag indicating if connection lines should be drawn in the view.
bool DrawRectangles
: Flag indicating if rectangles borders should be drawn around selected and linked items.
bool FillRectangles
: Flag indicating if rectangles should be filled on selected and linked items.
Color LinesColor
: Color used to draw lines between objects items (if DrawLines
is true
) and rectangle borders of selected and linked items (if DrawRectangles
is true
).
Color TempLinesColor
: Color used to draw lines between objects items during an item drag when a new link can be set (if DrawLines
is true
) and rectangle borders of the hovered item (if DrawRectangles
is true
).
Color RemoveLinesColor
: Color used to draw lines between objects items during an item drag when a link is about to be removed (if DrawLines
is true
) and rectangle borders of linked items which are about to be unlinked (if DrawRectangles
is true
).
Color RectanglesBackColor
: Color used to fill rectangles of the selected item and all linked items (if Fillectangles
is true
).
Color TempRectanglesBackColor
: Color used to fill rectangles of an hovered item when a new link can be set (if FillRectangles
is true
).
Color RemoveRectanglesBackColor
: Color used to fill rectangles of linked items which are about to be unlinked (if Fillectangles
is true
).
The control provide helper methods and properties:
IEnumerable<ListViewLinkerItemLinks> LeftItemsLinks
: Enumeration of all items of the left listview
and their linked items (from the right listview
)
IEnumerable<ListViewLinkerItemLinks> RightItemsLinks
: Enumeration of all items of the right listview
and their linked items (from the left listview
)
ListViewLinkerItemLinks GetItemLinks(ListViewItem, bool)
: Return the ListViewLinkerItemLinks
for a listview
item and can ensure to return a not null
value.
bool AreItemsLinked(ListViewItem, ListViewItem)
: Returns a flag indicating if the two items are linked or not.
void SetItemsAsLinked(ListViewItem, ListViewItem)
: Set two items as linked.
void SetItemsAsUnlinked(ListViewItem, ListViewItem)
: Set two items as unlinked.
void SetItemsLinking(ListViewItem, ListViewItem, bool)
: Set two items as linked or unlinked according to the third argument.
The shared code has a full XML documentation to know specificities of these functions.
Points of Interest
The solution also provides a useful class that helps to detect a scroll in a control and to fire an event with the scroll direction.
This was used because listview
s doesn't provide an OnScroll
event.
Todo
- Linking and unlinking items using the right-click should be realized during the MouseUp event instead of the
MouseDown
event.
- Display connections lines and rectangles during the
MouseDown
event if using the right-click.
- Cancel the drag-drop operation when the user is typing the
[Esc]
key during the action.
- Allow to display links of all items (if not displayed by the selected item) with a new color.
- Allow to display linked items in a tooltip for a hovered item and / or connections lines and rectangles if an hovered item is not the selected item with a new color.
History