|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
IntroductionIn this article, I have added the following commands:
Note: I will only support Visual Studio 8.0 on .NET 3.5 ! CommandsThe way I use WPF commands is straight forward, as described in the WPF SDK documentation, no extra infrastructure. GroupingMy first approach to group items was to use a "Specified element is already the logical child of another element.
Disconnect it first."
So I removed the items from the designer canvas and put them on the group canvas. Now it is interesting to understand what WPF did behind the scenes: as soon as I removed an item from the designer canvas, its template was unloaded and when I added it to the group canvas, a new template was loaded. Now do you remember the last article where I showed you how to connect designer items? There I connected items via connectors, connectors that were part of the designer item's template, a template that is lost as soon as I remove the item from the designer canvas. You see the problem? I have connected designer items via their templates and so the designer item itself has absolutely no information about existing connections. All connection related information is isolated in the designer item's template. Imagine a database diagram where the designer item's content is a database table. The table would never recognize any relation to other tables. One solution would be to tunnel the information from the template to the designer item to the table. A better solution is to redesign the application and divide the whole bulk into separate parts, e.g.
I will not start redesigning this code in the midst of an article, instead I will ride this 'view-only-approach' until the end of this article. The more painful this ride is, the more welcome a better solution will be. (I will cover a model backed designer in a future article.) So let's continue. An alternative approach to group designer items uses the following interface: public interface IGroupable
{
Guid ID { get; }
Guid ParentID { get; set; }
bool IsGroup { get; set; }
}
The idea is that the
This is simple, but the real work happens when I modify items (Select, Move, Resize, Copy, ...); with each of these operations I have to consider an item's group status. Sounds like a lot of work, but it's not as painful as it would be without LINQ. For this, I have wrapped most of the work into the Note: The SaveTo save a diagram, I have chosen to use a combination of XML and XAML. For the Here is an example of how I serialize designer items: XElement serializedItems = new XElement("DesignerItems",
from item in designerItems
let contentXaml = XamlWriter.Save(((DesignerItem)item).Content)
select new XElement("DesignerItem",
new XElement("Left", Canvas.GetLeft(item)),
new XElement("Top", Canvas.GetTop(item)),
new XElement("Width", item.Width),
new XElement("Height", item.Height),
new XElement("ID", item.ID),
new XElement("zIndex", Canvas.GetZIndex(item)),
new XElement("IsGroup", item.IsGroup),
new XElement("ParentID", item.ParentID),
new XElement("Content", contentXaml)
)
);
The XElement.Save(fileName)
OpenWhen loading a diagram from an XML file, we have to start with the designer items because we need their connectors to create connections. We have learned that connectors are part of the item's template, so the designer item has to load its template before we can continue. Fortunately the In the previous article, I provided a mechanism to customize the Note: When defining customized connectors, you must set the <s:Connector x:Name="Left" Orientation="Left"
VerticalAlignment="Center" HorizontalAlignment="Left"/>
Copy, Paste, Delete, CutThe Align, DistributeNot much to say about these commands, except that the reference item for alignment is the item that was selected at first (also called primary selection). This works only when you select items with the LeftMouseButton + Ctrl, or LeftMouseButton + Shift, but not if you use rubberband selection. OrderThe History
|
||||||||||||||||||||||