Proposed Control Architecture

Coordinator
Jun 17, 2009 at 6:40 AM

I have setup a page in the wiki for this here:

http://deepearth.codeplex.com/Wiki/View.aspx?title=Control%20Architecture

I would love to hear your feedback, the latest source code drop (changeset 20486): http://deepearth.codeplex.com/SourceControl/changeset/view/20486 has the code proposed for the new model.

In summary the idea is to make our controls here reusable as well as follow best practise, I'm very open to ideas at this early stage. I'm also very keen to migrate all the good work here and all the cool stuff we have waiting ASAP.

Coordinator
Jun 17, 2009 at 7:04 AM

So first up, I'm bad at naming.

1) What should we call the control project versus the specific map project (which only houses the implimentation of the interface)

currently:

DeepEarth.Client.Controls.CoordinatePanel

DeepEarth.Client.Controls.CoordinatePanel.BingMaps

2) What should we call the interface itself? I started off calling it IMap but thought it looked wrong.

currently:

ICoordinatePanelMap.cs

CoordinatePanelMap.cs

Jun 22, 2009 at 8:08 PM

Looking at the code, it looks like you are going to have memory leak problems with all of those events. I would suggest you look into turning CoordinatePanelMap into a behavior. If someone needs Silverlight 2 compatibility then you could provide a Silverlight.FX version of the behavior as well, the code is pretty much the same. By being a behavior you wouldn't need that MapInstance convention since the behavior is actually attached to the map and you get called to attach and detach yourself from the map so you don't need the page level code during the load event.

Naming-wise you would have:

 ICoordinatePanelBehavior

CoordinatePanelBehavior : ICoordinatePanelBehavior

Coordinator
Jun 23, 2009 at 11:41 PM

With the rumor that SL3 is due July 10 this may very well be the way to go. Everyone seems impressed with behaviors and their design time support. I'll need to look into these more as I thought they were more for functionality to be tied to an event rather then for toolkit style controls.

Looking into memory leaks I think the least we should do is impliment IDisposable and maybe use the nice DisposeHelper from the SLExtensions project here on codeplex to iterate through all children and make sure everything is disposed. I've certainly had this problem with pushpins previously.

Thanks for your comments Colin, will take a good look at Behaviors now.

Jun 26, 2009 at 11:57 PM
Edited Jun 26, 2009 at 11:58 PM

I found out that the SL3/Blend 3 Interactivity DLL actually works with SL2 as well. I put together an example of Coordinate panel redone as a behavior. It isn't perfect, I hard coded the margin and alignments for one thing, but it at least shows how clean the code looks for the user.

I uploaded the code as work item 4380.

Coordinator
Jun 30, 2009 at 6:33 AM

First up the best articles I found on behaviours are here:

http://blog.kirupa.com/?p=374

http://blog.kirupa.com/?p=378

Clearly the best feature here is the ability for the behaviour to get its instance of the map control from xaml alone. I agree it is much neater but will the designer get the design time support to position the control, set its properties and override its templates?

I'm not convinced behaviours are a replacement for a control. I see they are really useful for actions but I guess I havn't found a good example of replacing a control with a bahaviour.

As an aside I've redone the co-ordinate control as an abstract class to compare to the interface example. You end up with:

DeepEarth.Client.Controls.CoordinatePanel
Themes/generic.xaml (template)
CoordinatePanel.cs (Abstract class)

DeepEarth.Client.Controls.CoordinatePanel.BingMaps
CoordinatePanel.cs (Concrete class)

So you just need to put the BingMaps.CoordinatePanel on the page but unlike the behaviour example you still need to pass the MapInstance like so:

    public partial class Page
    {
        public Page()
        {
            InitializeComponent();
            Loaded += Page_Loaded;
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            coord.MapInstance = map;
        }
    }

So it occured to me, can we make a single behaviour that assigns the map to the MapInstance and get the best of both?

Coordinator
Jun 30, 2009 at 9:22 AM

Ok I've committed the next generation of proposed control code for the co-ordinate control, if you get latest your looking under:

DeepEarth.Client.Common

DeepEarth.Client.Controls.CoordinatePanel

DeepEarth.Client.Controls.CoordinatePanel.BingMaps

and setting "ExampleControlBingWeb" as the default web project to run it.

I've changed it over to be an abstract class and added a property "MapName" that can be set in xaml to the name of the map so you don't need any C# code if you don't want to set the MapInstance in code.

The control works in Blend, is fully templateable and I've implimented IDisposeable on everything.

Still to come is to break out what will be common Bing Map functions into a common project and potentially have an interface around the MapName / MapInstance stuff.

RE: Behaviours, I think these are going to be awesome for more action orientated functionality but I don't yet understand how they replace a control.

Coordinator
Jul 1, 2009 at 12:17 AM

I've updated the wiki page to reflect the changes:

http://deepearth.codeplex.com/Wiki/View.aspx?title=Control%20Architecture

I'm going to play with a generic abstract class / interface that sits under all controls today to see if it will help enforce and define some of the common functionlaity. Will keep this thread updated but hope we are close to having something usable as I'm keen to start getting all these controls uploaded for everyone to start using.

Coordinator
Jul 1, 2009 at 1:49 AM

So the problem is that our MapInstance property has to be generic, If I make this part of a base abstract class we end up with our control as CoordinatePanel<T> : ControlBase<T> where T : Control

And then this breaks the template system as you can define the TargetType in the generic.xaml, you could do a generic.xaml for each implimentation but that would just duplicate the work and the idea is to make this easier.

What we can do is have an interface eg:

using System;
using System.Windows.Controls;

namespace DeepEarth.Client.Common
{
    public interface IMapControl<T> : IDisposable where T : Control
    {
        T MapInstance { get; set; }
        string MapName { get; set; }
    }
}

Again our base abstract can't impliment this as it will kill the template but the implimentation could eg:

namespace DeepEarth.Client.Controls.CoordinatePanel.BingMaps
{
    public class CoordinatePanel : Controls.CoordinatePanel.CoordinatePanel, IMapControl<Map>
    {

And that would enforce having those properties and IDisposable. It would allow for helper to do things like dispose all children and change the MapInstance of all controls based on knowing the Interface only. I'm not sure if this adds any real value.