MySQL Entity Framework provider

by Administrator 30. September 2008 18:32

MySQL is a decent product.  I've been very critical of it in the past, but it has been evolving nicely.  It's probably the most popular open source database and plays nicely with .NET due to a solid ADO.Net provider.  What's been lacking up to this point, though, is LINQ to SQL support, and more recently a provider for the Entity Framework.  The EF has gotten a lot of flak, but I for one like it for the most part and I think it will hugely speed up a lot of database-heavy development. Sure, you need to write some extension methods to get around the lack of foresight for how change-tracking would work in ASP.Net applications, but once you've cracked that nut (and grokking aggregates with Entity SQL)  you can go back to happily writing LINQ queries.

I have been watching the MySQL forums for a while. The MySQL team had said during the Beta of VS2008 SP1 that there would be something we could test "real soon".  This was followed by months of radio silence.  Recently, silence was finally broken by the lead developer that September 30th was the date.  MySQL subsequently set up a webcast to demonstrate the new functionality.  Today, the day of the webcast, it seems that registered participants got messages saying that November 4th was the new date.  Unbelievable.  See: http://forums.mysql.com/read.php?38,194470,228269#msg-228269

When I was in consulting, we had a tongue-in-cheek (yet very true) rule about deadlines.  If the deadline was to be pushed back, it could only be pushed back by the amount of time remaining until the delivery date.  If you have 3 weeks until the deadline, you can only move the deadline out 3 weeks.  If it's due tomorrow, you can only push it out one day.  You do not wait until it's due today and push it back a month.  I'm sure there's a reason, but it's just bad form.  People are on the edge of their seats over this feature.  This isn't how open source is supposed to work.

Tags:

Run time is design time for AGT [11]

by Administrator 27. September 2008 18:31

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008.   This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

RC0

As promised, my next task was to make any changes needed to prepare the app so far for working with the RC0 Silverlight release.

Object Tag

The first thing I noticed is that when I tried to run the application I was presented with “Get Silverlight”.  I figured the version # had changed, but it was actually the type attribute of the object tag:

    <object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">

          <param name="source" value="ClientBin/DamonPayne.HTLayout.xap"/>

          <param name="onerror" value="onSilverlightError" />

          <param name="background" value="white" />

          <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

            <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>

          </a>

      </object>   

Note the type is now “application/x-silverlight-2”.

XAML weirdness

The next error I noticed was a seemingly uncatchable error that percolated all the way up to the onSilverlightError JavaScript function.

“Can not set ItemTemplate and DisplayMemberPath simultaneously.”

Looking at the XAML, this makes sense.

        <ListBox x:Name="_itemLst" Grid.Row="1" DisplayMemberPath="Name"  ItemsSource="{Binding ToolboxItems}" SelectedItem="{Binding Path=SelectedToolboxItem, Mode=TwoWay}">

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <StackPanel Orientation="Horizontal" >

                        <TextBlock Text="{Binding Name}"

This makes sense, it just didn’t cause an error before.  I’m setting DisplayMemberPath in XAML, which is then not used since I’ve provided the entire ItemTemplate.  It would be useful if the error told me which XAML file the error is in, but this is a small project so far and future Silverlight developers will be starting out with Silverlight 2 Release.

HitTest missed

At this point I thought I’d better do a Clean Solution just to be safe, and sure enough this turned up another issue.  At some point, my DesignSurface.HitTest method (required by IDropTarget) disappeared.  The Clean Solution found this out for me.  Looking back through my code snapshots taken at the end of each article, it’s been gone for quite some time.  This behavior from VS2008/Silverlight Tools is just not ok.  This was my last breaking change though.  UIElement.HitTest is gone, replaced with a method in VisualTreeHelper:

        public IEnumerable<UIElement> HitTest(Point p)

        {

            return VisualTreeHelper.FindElementsInHostCoordinates(p, LayoutRoot);

   }

Moving On

I find now that my Selection code is absolutely broken, but that was under repair anyway.

Source code: Because the code was in a state of flux pending the selection/sizing updates, the next source code will be at the end of AGT[12].

Tags:

Silverlight RC 0

by Administrator 26. September 2008 21:56

You have probably seen that Silverlight RC 0 is now available: http://weblogs.asp.net/scottgu/archive/2008/09/25/silverlight-2-release-candidate-now-available.aspx

I was in the middle of writing AGT[11] and got sick, requiring a 16 hour sleeping spree, and I'm still not over it. AGT[11] also represented some frustrating material, so it was going slow.  Figuring out the Silverlight Layout-->Measure-->Clip-->Render process well enough to acheive my next goal is turning out to be challenging.  I'll preface it with some recommended reading.  At any rate, the material for AGT[11] will now become AGT[12].  The articles and the live demo are immediately switching over to use Silverlight RC0 before I accumulate any more breaking changes or write code to Measure behavior that changes.  Some of the solutions I was pursuing just became private/internal/sealed as of yesterday.

Recommended reading:

http://msdn.microsoft.com/en-us/library/cc645025(VS.95).aspx

http://msdn.microsoft.com/en-us/library/cc189087(VS.95).aspx

http://blogs.msdn.com/silverlight_sdk/archive/2008/05/06/more-on-layout-and-the-layoutinformation-apis.aspx

http://silverlight.net/forums/t/20520.aspx

http://nerddawg.blogspot.com/2008/04/silverlight-2-layout-and-rendering.html

http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.layoutinformation_members(VS.95).aspx

 

Tags:

Just say no to corporate welfare

by Administrator 25. September 2008 17:34

I have contacted my Federal representatives today to let them know I am firmly against the proposed $700 billion bailout proposal.  You should do the same.

Tags:

Roger Ebert and the age of credulity

by Administrator 24. September 2008 05:06

http://blogs.suntimes.com/ebert/2008/09/this_is_the_dawning_of_the_age.html

Art imitates life, and life in turn imitates art (which is a part of life)

I have often remarked to friends that the enduring success of Roger Ebert is hard to understand, though I am happy to see it.  After all, this is the 2000's we are living in.  He is, forgive me, not a particularly attractive man, nor does he speak and write at a level accessible to to the average high school graduate.  This is after all the age in which we vote for politicians based not on their qualifications to make decisions that are "far above our pay grade" but rather on whether or not we would feel comfortable having them over for BBQ chicken without having a chance to clean the house first or if they would fit in at our local church.  What I mean to say is that Roger Ebert does not have qualities which would immediately invoke the words "mass appeal".  He is, rather, an elitist - a word which should be badge of honor and not the insult is has become in our praise of mediocrity in this nation.

Roger Ebert writes thoughtful insights about Film, which I consider to be our highest art form to date.  Why?  Because it combines music, philosophy, dancing, drama, words, and technology into a single medium.  Each of these expressions can be profound in themselves, but combined into a single human experience moving through time can approach something truly sublime.   Surely all these things are excellent achievements of Humans and the combinatorial effects of overlapping them are worthwile of educated commentary.   The success of Roger Ebert, then, I attribute to there being just enough intelligent people in America who care just enough about things that matter to humans to give this man an enduring audience.

Ebert tells us that these days there are few rewards for critical thinking, and I must sadly agree to a point.  It would seem to me that his true talents lie not in interpreting Art, but in observing and reporting on human behavior.  Keep up the good work, sir.

Tags:

Run time is design time for AGT [10]

by Administrator 23. September 2008 03:28

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008.   This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Selection

Now that we’ve got things on the surface, we need to think about selecting, moving, editing, and resizing them.  It makes sense for Selection to come first.

Selection is slightly more complicated than it sounds.  In a tool like VS2008 or Visio things could be added or removed from the selection in several ways:

·         Clicking on a component

·         Control+Click on multiple components to select and deselect

·         Shift+Click to add contiguous components to the selection

·         Click and draw a rectangle, selecting components within the bounds of said rectangle.

Since I’m extending the olive branch to the dozens and dozens of unfortunate Mac users in the world, I’ll have to make any gesture code I write smart enough to not use any normal keys that are missing from the Mac, such as: Control, Window Key, Right-click Key, Pause/Break, up arrow, and the letter Q.

Back in the Dark Ages when I was writing code to host the WinForms 2 design surface, I think my selection service implementation was quite a few lines of code.  While I still like the idea of a selection service, I’m not going to go look at the old code and corrupt my pure thoughts.  First, let’s create a cross platform Keyboard service:

    public class CrossPlatformKeyboardService : IKeyboardService

    {

        /// <summary>

        /// Control key, or open-apple on the Mac "platform"

        /// </summary>

        public bool ControlKeyDown

        {

            get

            {

                return ( Test(ModifierKeys.Control) || Test(ModifierKeys.Apple));

            }

        }

 

        public bool AltKeyDown

        {

            get { return Test(ModifierKeys.Alt); }

        }

 

        public bool ShiftDown

        {

            get { return Test(ModifierKeys.Shift); }

        }

 

        protected bool Test(ModifierKeys target)

        {

            return target == (target & Keyboard.Modifiers);

        }

Next I’ll define what I expect the interface for a selection service to be.

    public interface ISelectionService : IService

    {

        void SetSelectedControls(IList<IDesignableControl> selection);

        IList<IDesignableControl> GetSelection();

        int SelectionCount { get; }

        IDesignableControl PrimarySelection { get; }

        event EventHandler SelectionChanged;

    }

In WinForms, adding to the ISelectionService can optionally come with a parameter of type “SelectionType”, which is a discriminator for things like adding to a selection vs. starting a new selection.  I’d rather leave those details behind the ISelectionService wherever possible.  You will also note that I am using a plain old .Net event here and not something from EventAggregator.  I feel this is highly appropriate in this case.  The EventAggregator exists so that components can respond to interesting events without referencing each other, but selection events are specific to this Service, and components that need ISelectionService will magically receive it from the container.   Now I can start working on a default ISelectionService implementation, with a dependency on IKeyboardService.

Siteing, not Sighting

We need to take another step before Selection can make sense.  The WinForms designer has the notion of an ISite, where an ISite is an adapter between a designed component and its designer.  Once sited, the component can request various things of its container.  While not quite what I’m about to do, it’s a point for interested users to research.   I will explain this concept further in the next article.  I have created a UserControl called DesignSite.  DesignSite contains a border whose thickness is set to zero by default.  Inside DefaultDesignTypeCreator I shove the real IDesignableControl inside my DesignSite and let DesignSite handle the selection code when the real IDesignableControl is clicked on.

Back to Selection

The Site mentioned above wires up selection by resolving the ISelectionService.  Here, then, is the selection service implementation.

    public class DefaultSelectionService : ISelectionService

    {

        public DefaultSelectionService()

        {

            _selection = new List<IDesignableControl>();

        }

 

        public IKeyboardService KBService { get; set; }

 

        private List<IDesignableControl> _selection;

 

        public void Select(System.Collections.Generic.IList<IDesignableControl> incoming)

        {

            if (!KBService.ControlKeyDown)

            {

                _selection.Clear();

                _selection.AddRange(incoming);

                OnSelectionChanged();           

            }

            else

            {

                foreach (IDesignableControl idc in incoming)

                {

                    if (!_selection.Contains(idc))

                    {

                        _selection.Add(idc);

                    }

                    OnSelectionChanged();           

                }

            }           

        }

 

        public System.Collections.Generic.IList<IDesignableControl> GetSelection()

        {

            return _selection;

        }

 

        public int SelectionCount

        {

            get { return _selection.Count; }

        }

 

        public IDesignableControl PrimarySelection

        {

            get

            {

                return _selection[0];

            }

        }

 

        public event EventHandler SelectionChanged;

 

        protected void OnSelectionChanged()

        {

            if (null != SelectionChanged)

            {

                SelectionChanged(this, EventArgs.Empty);

            }

        }

Much simpler and shorter than I remember the WinForms implementation I remember.  We’ll see if I eat crow for saying so later.  Here is my site-style selection with a single component selected.

Shown here with multiple components selected by holding in Control or Open Apple:

You will note I don’t have any little “knobs” on the corners or anything.  I like how this looks better with a solid border and a gradient brush.  As we saw with Couch v1, perhaps my taste in visual appeal should not be trusted.  Speaking of couches, I have a chair now too.  You can take a look at my freshly painted Red Chair in the live demo.  Live demo….?

More ControlExtensions

Ever since being enlightened by Generics (the answer to everything) using the (cast) bothers me.  Casting using “as” bothers me more.  For this reason, I don’t know why the whole DependencyProperty framework deals with getting and setting of values as Object.  When I ported some code from Silverlight 2 beta 1 to beta 2, some of it was broken because I was using SetValue(Canvas.Left, 3) when in fact Canvas.Left wanted to be of type double and some auto-conversion was lost in the move to beta 2.  This error only pops up at runtime since SetValue takes type Object.  At least I can save myself some casting here and there by adding another extension method:

        public static T GetValue<T>(this DependencyObject d, DependencyProperty p)

        {

            return (T)d.GetValue(p);

        }

Which allows glorious code like:

double left = SiteBorder.GetValue<double>(Canvas.LeftProperty);

It isn’t much but I’ll take it.

Conclusion & Next Steps

I have created a live demo at http://www.damonpayne.com/agt ; obviously this is a work in progress but feedback is welcome. 

I have a pretty good idea how I’m going to do resizing, that will come next.  After that I will do multi-select by drawing a rectangle and then Moving.  After moving works I will have to think of how I want object editing to work, some kind of Property Grid I’m sure.  From there, I’ll have to take stock of where I’m at, review my goals, and decide what to do next.

Source code:DamonPayne.AGT[10].zip (1.28 MB)

Tags:

Run time is design time for AGT[9]

by Administrator 22. September 2008 01:25

The AGT (Argentum Tela) series of articles is an effort to do two things. Usually an idea is presented only in its finished form. The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches. The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008. This type of application has all sorts of interesting uses. My example is a Home Theater layout tool. Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Visual Refactoring

Since this is a Silverlight application I thought I should spend some time making it look good. I hit my frustration limit in a very short period of time and what you see here is as far as I got. I am guessing Styling is not entirely baked in Silverlight 2 beta 2, or else doing a complete control template is really the way to go.

My first issue was with fonts. I downloaded a copy of the Trajan Regular font. Ever since Klipsch started using Trajan pro in the Palladium branding I’ve been digging the Trajan font family. At any rate, it seems that Silverlight is very picky about using extra fonts, be they set from a style or per control. Worse, it’s very difficult to track down where the issue might be. I have three primary tools available to me for Silverlight debugging: Blend 2.5 June CTP, VS2008 SP1, and running the application for inspection. Debugging is not fun when all three tools show different output, check out the ToolboxView:

clip_image002

Blend shows the correct font and color. VS2008 shows the correct nothing. Runtime shows the correct color but not font. I’ve tried obvious things like double checking relative paths and so forth. At this point I’m admitting defeat and moving on. At least my bad taste and visual look stolen from Klipschcorner’s CSS is better than black and grey. Right? Let’s skip to the punchline, here is what the application looks like now:

clip_image004

Couch++

I tricked a visual designer into making me a better purple couch. This person happens to be an extreme Adobe fanboy, to the degree that they didn’t believe me when I said there were other drawing programs for both vector and raster graphics. The Adobe fans are easily worse than the Mac fans. At any rate, that sure looks like a couch, at least. It’s rather large in relation to the design surface, but we’ll fix that with resizification later.

Speakers

I haven’t really thought of what all I want to include in the example HT Layout program, but I figured some speakers would be nice. I’m getting slightly better at drawing some things in Blend: these speakers look better than my original couch. If you’re not familiar with horn-loaded speakers you’ll have to trust me that the white horn shape is actually a reasonable caricature.

Conclusion

I’ll refactor later as I get to read more about the control templating and style creation. I think the app is starting to look like a real program, and we’re still less than 1000 lines of code. The next articles are not written yet, but the next step is to implement functionality that allows me to move, resize, and otherwise Transform things once they are on the designer surface. As it turns out, this is a very interesting problem for all sorts of reasons. I’m not breaking my Reality Blogging pledge, but remember I’ve done this in WinForms before, and I recall things like “selection” being more complex than it sounds: http://msdn.microsoft.com/en-us/library/system.componentmodel.design.iselectionservice_members.aspx . Once selection is implemented moving and resizing come free in WinForms, and I’ve got to build those from scratch now. I’m sure I’ll be spending some time in traffic this week and I’ll spend many mental cycles thinking about the interactions.

Source Code:DamonPayne.AGT[9].zip (1.26 MB)

Tags:

Windows Live Writer

by Administrator 22. September 2008 01:16

This article and AGT[8] were written with Windows Live Writer, after Larry talked me into trying it.  So far, I really like the idea, but the implementation could be better.  I typically write my articles in Word 2007, since I may be working on one for days or weeks.  Cut 'n pasting out of Word into the DasBlog FreeTextBox just works.  Sure, it generates the ugliest HTML you've ever seen, but it looks like code in both IE7 and FF3.  Copy/pasting out of VS2008 into Live Writer looks like this:

ToolboxItem speakItem = new ToolboxItem("Tower speaker", "This is a generic 2-way tower speaker with horn-loaded mid & high range", typeof(HornSpeaker));
Toolbox.AddItem(speakItem, "Audio");

Copy/pasting out of MS Word 2007 into Live Writer looks like this, using the "keep formatting" option.

            ToolboxItem speakItem = new ToolboxItem("Tower speaker", "This is a generic 2-way tower speaker with horn-loaded mid & high range", typeof(HornSpeaker));

            Toolbox.AddItem(speakItem, "Audio");

It's not bad, but it insists on inserting some extra spaces between lines.  I've also been uploading a .zip file of the source code as it stands at the end of each article, and I find no way to do this from Live Writer - perhaps that's not supported by the blogger API.  I do like it inserting & uploading images for me.

For complex articles, I'll still be copy/pasting from Word, but for a free program I do rather like Live Writer.

Tags:

Run time is design time for AGT[8]

by Administrator 21. September 2008 12:32

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Code Refactoring

I’m eager to get on to some of the cool next steps like the ability to move and resize things on the Design Surface, but my TODOs are starting to pile up.  I’d rather not get too far into this and find that some fundamental thing that was bothering me is now a real issue.  Using the Task List feature in VS2008, I’ve got 20 things I should at least look at.

Namespaces

I’ve been thinking lately about some other Silverlight projects I have on the back burner, and how nice it would be to keep them in mind for the IoC stuff.  Therefore, I should rename DamonPayne.AGT.IoC to just DamonPayne.AG.IoC.  I like the fact that VS2008 makes the default namespace of a project match the project name, but the tooling stops there.  I have to rename the project, edit the default namespace, edit the assembly name, and do a global find/replace on the top level namespace.  Lame.  58 occurances replaced, and the Design and HTLayout projects reflect the new name; it even built the first time.

Events

While sitting in traffic I had the idea to overload += for my AggregateEvent<T> and make it feel more like a built in .NET event type.  As it turns out this won’t work the way I wanted it too so I erased that TODO.  I also got rid of the static “Test” method in EventAggregator.

Reflection

I have several TODOs related to reflection code.  The first one suggests Caching Type and Property information to make reflection go faster.  I’ll leave that alone for now and come back to it.

Tidy up: I found that there is a Type.EmptyTypes static var, similar to EventArgs.Empty.  I found three places where I could substitute Type.EmptyTypes.

I also found that I had some duplicate interface code and I could add some things to my TypeExtensions static class:

       public static bool ImplementsInterface(this Type t, Type intefaceType)

        {

            if (intefaceType.IsInterface)

            {

                Type[] interfaces = t.GetInterfaces();

                if (interfaces.Contains<Type>(intefaceType))

                {

                    return true;

                }

            }

            return false;

        }

 

        public static bool ImplementsInterface(this object o, Type intefaceType)

        {

            return ImplementsInterface(o.GetType(), intefaceType);

        }  

I was able to go through ServiceManager and ComponentBuilder and clean up some code using these Extension methods.

Several calls to invoking a Type’s default constructor can be replaced with Activator.CreateInstance; this was done throughout.  The 1-arg constructor for Presenter types was also replaced with a call to Activator.

Control Extensions

On suspicion that I would need the ability to scale controls without distorting their aspect ratio in the future, I left myself a note to create an extension method to determine an aspect ratio preserving method:

    public static class ControlExtensions

    {

        public static double UniformScaleAmount(this Control c, double maxDimension)

        {

            double originaltWidth = c.Width;

            double originalHeight = c.Height;

            double uniformScaleAmount = Math.Min(maxDimension / originaltWidth, maxDimension/ originalHeight);

            return uniformScaleAmount;

        }

    }

At this point, I am staring sideways with some dread at the remaining TODO items.  The remaining items involve:

1.       Revisit the relationship between ServiceManager and ComponentBuilder to see what, if anything, should be done about the crosstalk.

2.       The ToolboxCategory code doesn’t work how I’d like, and fixing it will involve a lot of digging deeper on the Silverlight control templating framework.

3.       There are several visual notes I’ve made to myself, I will address those in the next article.

4.       Something is amuck with InterfaceMocker, it only works once.

5.       I need to decide how I want configuration to work.

Configuration can have its own article I think, for now I’ll at least look into ServiceManager, ComponentBuilder, and InterfaceMocker.

Reflection Emit Redux

Inside ServiceManager.GenerateProxy, I did not take into account the fact that more than one client may ask for a given interface implementation.  In my startup code, I was able to get “Duplicate Type name in assembly” from time to time.  I just needed to add a check before building the type mock:

private static Dictionary<string, object> _proxies;

            string proxyName = t.Name+"TempProxy";

            if (_proxies.ContainsKey(proxyName))

            {

                return _proxies[proxyName];

            }

 

            object o = null;

            ModuleBuilder module = GetDynamicModuleBuilder();

            //

            TypeBuilder typeBuilder = module.DefineType(proxyName,

                TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Class,typeof(object) );

            typeBuilder.AddInterfaceImplementation(t);

No more proxy errors.

ServiceManager loves ComponentBuilder

As soon as I introduced ComponentBuilder I should have moved all object creation code to it.  But I didn’t, so now here I am looking at several TODO items.  From ServiceManager.ObtainDefaultInstance:

                o = Activator.CreateInstance(t);

                //TODO: maybe use the ComponentBuilder to create the damn thing in the first place

                ComponentBuilder.ResolveServiceDependencies(o);

                ComponentBuilder.BuildPresenters(o);

ComponentBuilder.Create:

        public static T Create<T>() where T :new ()

        {

            T instance = new T();

 

            ResolveServiceDependencies(instance);

            BuildPresenters(instance);

            ServiceManager.ManageInstance(instance);//TODO: verify this was the right design choice later

 

            return instance;

        }

Furthur, ServiceManager.ManageInstance (which might have been a hairy issue otherwise) is used from only a single place, ComponentBuilder.Create.  Creating a non-generic override of Create is step 1:

        public static T Create<T>() where T :new ()

        {

            T instance = default(T);

            instance = (T)Create(typeof(T));          

            return instance;

        }

 

        public static object Create(Type t)

        {

            object instance = Activator.CreateInstance(t);

            ResolveServiceDependencies(instance);

            BuildPresenters(instance);

            return instance;

        }

I hate having to go back and write code that involves casting and Type, when generics are so much cleaner, but such is life.  While chasing down the resulting bugs, I realized Manage(List<Type> types) and ManageInstance(object provider) were almost the same method.  The Manage method is refactored to call ManageInstance:

        public static void Manage(List<Type> types)

        {

            Type baseServiceType = typeof(IService);

 

            foreach (Type t in types)

            {

                object instance = ObtainDefaultInstance(t);

                ManageInstance(instance);

            }

        }

Lovely, more TODOs off my list and some unintended good side effects as well.

Unit Testing

Unit Tests allow us to refactor with impunity.  The fact that this project was ~500 loc doesn’t hurt either.

I Google “Silverlight 2 beta 2 unit test” and look what I find: http://code.msdn.microsoft.com/silverlightut/Release/ProjectReleases.aspx?ReleaseId=1543

I have to admit I had been thinking about making my own or Porting XUnit, but now I don’t have to.  I’ve grown to like the minimalistic XUnit interface, and I feel blind without NCover, but this will do for now.

Source code: DamonPayne.AGT[8].zip (622.87 KB)

Tags:

Run time is design time for AGT [7]

by Administrator 20. September 2008 19:06

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Part 8 in a 50 part series begins...

Drag and Drop

It’s time to try dragging something out of the Toolbox and onto the DesignSurface.

We start dragging by wiring up events inside the ToolboxCategoryControl.  We’ve already established a mechanism for making sure only one ToolboxItem is ever selected, and that the ToolboxView owns the ToolboxCategoryControl.  We define a normal local dragstart event:

        void cat_DragStart(object sender, EventArgs e)

        {

            ToolboxItem tbi = SelectedItem;//Will already be populated from event wireup

            DragDropManager.BeginDrag(tbi);

        }

I have implemented the cleverly named DefaultDragDropManager in the DamonPayne.AGT.Design.Services namespace to handle the task.  The first thing DDDM does is obtain a drag-time representation of the Control visual.  This is one of the places where we start diverging more and more from how VS2008 works and looks today. While I’m not ready for the Visual Refactoring stage yet, we can clearly do better than a tiny mouse cursor with a “+” next to it.  This is what IDragTypeCreator is for: to provide a pluggable mechanism for building a better representation of what you’re dragging around than a mouse cursor.  I created a special DragContainer control for this purpose in DamonPayne.AGT.Design.Controls.  Here is the entire DefaultDragTypeCreator.CreateDragRepresentation method:

        public Control CreateDragRepresentation(Type t)

        {

            //Default behavior:

            DragContainer dc = new DragContainer();

            Control c = (Control)Activator.CreateInstance(t);

            //Thanks to http://www.jeffblankenburg.com/2008/04/how-about-some-code-simple-resizing-in.html for scaling code

            //TODO, extension method for uniform scale size?

            double originaltWidth = c.Width;

            double originalHeight = c.Height;

            double uniformScaleAmount = Math.Min(MAX_DIMENSION / originaltWidth, MAX_DIMENSION / originalHeight);

            ScaleTransform st = new ScaleTransform();

            st.ScaleX = uniformScaleAmount;

            st.ScaleY = uniformScaleAmount;

            c.RenderTransform = st;

            c.InvalidateMeasure();           

            c.UpdateLayout();

           

            //TODO: why couldn't I force this to recalc size here after setting render transform?

            double estimatedNewWidth = c.Width * uniformScaleAmount;

            double estimatedNewHeight = c.Height * uniformScaleAmount;

            double left = (dc.Width / 2.0D) - (estimatedNewWidth / 2.0D);

            double top = (dc.Height / 2.0D) - (estimatedNewHeight / 2.0D);

            c.SetValue(Canvas.LeftProperty, left);

            c.SetValue(Canvas.TopProperty, top);

            dc.LayoutRoot.Children.Add(c);

            dc.Opacity = .65D;

            dc.LayoutRoot.Opacity = .65D;

           

            return dc;

        }

I am basically creating an instance of whatever Type I was given, which ultimately came from ToolboxItem.Type.  Then I scale the instance down to where it will fit in my DragContainer and return the DragContainer.  With this in hand, DefaultDragDropManager wires up the mouse events for dragging around: basically when mouse left button goes up we do a hit check to see if there is an IDropTarget registered with us that would be under the current mouse position.  With the events set, we add the DragContainer control to the root visual of the Silverlight application.

Design Surface

The next thing I need to actually implement is the DesignSurface control, implementing IDropTarget.   This needs to be added into the IRegionManager way back when the ToolboxView and MessageConsole are created.  I’ve resized the whole Page such that I can fit a 480x640 gray DesignSurface in there.  You can now see me take my drag-time couch representation over to the design surface:

As soon as I got into developing the drop part, I realized I was in the Silverlight world, thinking like a WinForms developer.  Silverlight has built in hit test code already and I don’t need to do anything with Bounds.  The IDropTarget interface is thefore modified to use UIElement.HitTest(Point), so the EndDrag method can now do this:

        public virtual void EndDrag(MouseButtonEventArgs e)

        {

            RegionManager.TopLevelContainer.Children.Remove(_dragRepresentation);

            _dragRepresentation = null;

           

            foreach (IDropTarget target in _dropTargets)

            {

                if (target.IsHitTestVisible)

                {

                    IEnumerable<UIElement> elements = target.HitTest(_mousePos);

                    if (elements.GetEnumerator().MoveNext())//hit test succeed

                    {

                        IDesignableControl ctrl = DesignCreator.CreateInstance(_draggingType);

                        target.OnDrop(ctrl);

                    }

                }

            }

_draggingType = null;

        }

As soon as we enter OnDrop, the design time representation is worthless and we throw it away.  We’ll either be building the real control the surface or simply cleaning up.  I believe in the last article I described the interaction as the DesignSurface calling the creation method from OnDrop, but it makes more sense to put it here now.    For now, the IDesignTypeCreator simply instantiates the appropriate Type.  DesignSurface.OnDrop is incredibly simple for now:

        public void OnDrop(IDesignableControl dc)

        {

            dc.Visual.SetValue(Canvas.LeftProperty, _localMousePos.X);

            dc.Visual.SetValue(Canvas.TopProperty, _localMousePos.Y);

            LayoutRoot.Children.Add(dc.Visual);

        }

Success!  Here’s the very nice looking purple couch on the design surface.

Clearly there is tons of work to be done still, but I was shocked when I actually ran metrics: this just a little over 500 lines of code so far!

Source code: DamonPayne.AGT[7].zip (613.16 KB)

Tags:

About the author

Damon Payne is a Microsoft MVP specializing in Smart Client solution architecture. 

INETA Community Speakers Program

Month List

Page List

flickr photostream