Friday, June 13, 2008

I’ve been busy sharpening my Silverlight skills and created my very own button, complete with VSM.

The button (‘rjButton’) inherits from contentControl and in the project there is a generic.xaml which defines a default look for the button, including VSM definitions and state transitions.
When loading up my solution in Blend, I can happily get the rjButton in my page. It looks correct. However, when I ‘Edit a copy’ of the template, nothing shows up!! Funnily enough, when I use ‘Create empty’, the correct states do show up.

I was unable to google-fix the problem. I would guess that when you use ‘create empty’, Blend just looks at the attributes on your class and shows the correct states. When you ‘Edit a copy’, Blend looks for the template and can not find any. Somehow it is unaware of the link to the style in generic.xaml, and it creates an empty style.

I’ve double checked the behavior with the TabControl, which is also a control that is defined in an external control, and it works the same.
I'm not sure why controls included in the framework do work correctly. I've taken a look with reflector and I've seen nothing out of the ordinary.

You can work around this by naming the style and explicitly tell the control to use the style. But then again, it might be easier to just copy the style (use David's excellent style browser here).

If you know what is going on, leave a comment!

[update: jasonxz knows: I was informed, today, that Blend does not, yet, support the "edit a copy" functionality of a Template that is not defined in System.Windows.dll. Thnx! ]

Friday, June 13, 2008 5:45:21 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

I just spent way too much time figuring out why my VisualStateManager suddenly started giving errors. Without ‘break on all exceptions’ I got a ‘Catastrophic error’. With breaking on all exceptions I could finally see that the layout system was trying to layout the visualstatemanager.

I basically had specified my vsm directly under the controltemplate, instead of defining it inside the grid. Whoops!

Friday, June 13, 2008 3:01:00 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Wednesday, June 11, 2008

I was triggered to spend some time on thinking about deeplinking, when I was listening to a podcast with Neal Ford, here.
In it, he has quite a few arguments why something like Silverlight (and Flex for that matter) will never amount to anything. I disagree with almost all of his points, but one stuck with me more: the inability to do deeplinking.

Let me start off by saying that I think the ‘normal’ html world has reached maturity and should soon begin to disappear. As almost everything in the world, technology adoption follows a wave pattern. Html has had some great advantages which made it easy to adopt. However, as computing power increases and humans become more accustomed to great applications, html as a platform does not deliver anymore. It was rejuvenated by the Ajax revolution, but in the end, you are always fighting against the restrictions that it imposes.

Those restrictions are no longer necessary. Flash did not deliver as a RIA platform, but Flex seems very capable, as does Silverlight. It will take a few years, but the demand for rich clients will drive the adoption of said technologies.

Being able to do deeplinking, is an important part of the experience and usability. The more I thought about it, the more I agreed on this. Although I think that browsers (as we know them) will cease to exist pretty soon or more likely: change to meet new needs, for the next few years we will have to deal with the restrictions they impose.
So, I started to think about how we can solve the deeplinking issue for Silverlight.

I had a flash of brilliance when I thought of the achor (#) sign in url’s. They can be navigated to, but the page is not reloaded. Exactly what was needed for deeplinking.
After doing some fast research, I discovered half the world had already thought of this trick and it is heavily used by the Flex world.
That discovery ruined my chances to score some ‘smart'-points with my girlfriend, but it won't keep me from implementing my idea ;-)

The basic idea

The idea is to get to the url at the beginning of the application and treat everything after the # sign as 'state'. This state is used by the components in our application to initialize themselves to the correct state. For instance, show the help page, or the products page.
When a component is changed and it is important enough to reflect this change in the url, we use javascript to navigate to the new url. The browser will recognize that only the anchor has changed, and will not really browse there. However, the user can now confidently copy the url.

It's pretty easy.

Two approaches

Using a navigationcontroller.
Your application could instantiate one navigationcontroller. This controller would be used inside your application to show different usercontrols etcetera. I think such an approach is well suited for a MVC-style of application architecture.
Obviously, since all your navigation is taken care of by a central component, it would be very easy to take care of 'serializing' its state to the url.

Using per component approach.
If you're just not that kind of person, you could also just make the components you care about do the (de)serializing. So, possibly react to the Loaded event of a component and reading the url to see how to initialize it.
I've taken this a step further and created a class that serializes the vertical offset of a Scrollviewer. It can be used like so:

  1         <ScrollViewer x:Name="sv1" VerticalScrollBarVisibility="Auto" Margin="10">
  2             <nav:ScrollviewerOffsetStateAttacher.Register>
  3                 <nav:ScrollviewerOffsetState TemplateName="HelpTemplate" PartName="pos1" />
  4             </nav:ScrollviewerOffsetStateAttacher.Register>
  5         <TextBlock TextWrapping="Wrap">   
6 Lorem ipsum dolor sit amet, conse

(pretty radical, isn't it. Here I'm serializing the amount of scrolled pixels to the url. That's something else than just which page you are viewing!)

Some more code

First off, you need to think about how the url is serialized. Some kind of template needs to be known to the system. And, different templates should be available for different parts of your application. So, during initialization of my application I do this:

            NavigationState.RegisterTemplate("MainNavigationTemplate", "mainpage");
            NavigationState.RegisterTemplate("ProductTemplate", "mainpage/product/detailpos");
            NavigationState.RegisterTemplate("HelpTemplate", "mainpage/pos1/pos2");

A better approach might be to supply regex expressions.

As you have figured out by now, I'm using a static class 'NavigationState' to manage my url fiddling. It contains a SetNamedPartState and a GetNamedPartState method. So when I navigate to the Products page, I might do this:

appController.NavigateToPage(typeof(Products));
NavigationState.SetNamedPartState("mainpage", "ProductTemplate", "products");


I'm telling it to use the producttemplate and set the mainpage part of that template to the state 'products'.
During the load though, I do the opposite:

string state = NavigationState.GetNamedPartState("mainpage", "MainNavigationTemplate");
if (!String.IsNullOrEmpty(state))
{
    if (state == "products")
        ProductsSelected();
    else if (state == "help")
        HelpSelected();
}

Getting the url is easy:
string uri = HtmlPage.Document.DocumentUri.ToString();

Setting it is only slightly harder:
HtmlPage.Window.Eval(String.Format("window.navigate('{0}#{1}');",
    NavigationApplicationString, InternalStateString));

Conclusion, work ahead

It's pretty a pretty simple idea. I like the way I attached a 'state' object to a scrollviewer control to make a no-code, designer friendly experience possible.

If someone would get serious about this, I guess they would take a look at the asp.net mvc approach. They also hook the url's you are setting, to the back button(!) So, there should be good crossbrowser javascript available.

Also, a good and flexible url parsing engine is necessary.

Finally, when you take the approach of one controller doing all the hard work, nothing much has to be done. However, I can see the creation of all kinds of specific classes that can be attached to controls to make them 'url-persistable' (think of selecting the right listbox item).

Try it out

The homepage of our sample application:
http://www.sitechno.com/silverlight/deeplinking/deeplinkingtestpage.html

Two url's with state in them:
http://www.sitechno.com/silverlight/deeplinking/deeplinkingtestpage.html#products/SqlServer/760
http://www.sitechno.com/silverlight/deeplinking/deeplinkingtestpage.html#help/309/1166

I will not keep this application available forever and probably not update it to the release version of beta2.

 

Who is going to make themselves useful by creating a robust solution? Leave a comment of mail me if you want the source code!

Wednesday, June 11, 2008 8:48:01 PM (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
 Thursday, June 05, 2008

Okay, I've been busy with other stuff in my life, I'll blog about soon. Suffice it to say, I'm going to be able to focus my time more on Silverlight now ;-)

The Silverlight team is announcing beta 2 with this post. It's a pretty long list with changes, and it's looking very good! Here are a few of my favorites:

  • They included some controls into the runtime. So more goodies without added download size.
  • A visual tree helper. I'm looking for more information on this. As you know, SL does not have the same concept of a seperate visual tree and logical tree as WPF does. They instead opted to not differentiate. Does this helper mean that the two models come closer to each other?
  • Per binding level validation.
  • Binding to attached properties! Yay!
  • OnItemsChanged method
  • Fallback value during conversion
  • Duplex communication. Oh dear, they really hit the sweet spot here. This allows you to push data to the client during a call.

The big one for me is support for UIAutomation though. I'm not sure if it is supported fully, but this means you can test your controls with actual 'human'-like input. I think this is important when building an application with a late-bound system like Xaml-binding.

The whole blogosphere is raving about the new VisualStateManager. It is a highlevel api to work with your states. The blend team is able to give you a much improved templating story because of it. Read about it here or here.

Thursday, June 05, 2008 11:14:48 AM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Tuesday, April 29, 2008

I've recently moved this blog to another host. Everything seems to work, except for access denied errors on the comments.

I'm using DasBlog which writes to the filesystem. I'm able to post new posts without problems, but comments don't work.

If you have any comments, feel free to email me. I've already received a few, and will be answering them.

[update: not sure why, but I removed the allcomments.xml, and there is no longer an error. However, no new 'allcomments.xml' file is created, so don't know what's up with that!]

Tuesday, April 29, 2008 2:33:19 PM (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
 Wednesday, April 23, 2008

Daniel Simmons commented on the next beta of EF where the team has worked with the WCF team to allow for better serialization (in an interoperable way) of complete graphs and relations. I'm very excited to hear that, but as Julie Lerman pointed out: it's also kind of frustrating for me. ;-)

As you know, I have 3 different pieces of technology that help make the possibility of n-tier disconnected scenario easy.

One of those pieces is the circular serializer, that was created to change the way WCF serializes circular references. However, it has grown to also support 'original' values.

My current plan is as follows:
I will wait to see how WCF serializes entity graphs in the next beta. I expect to see that my circular serializer is no longer necessary. Hopefully I will be able to remove it all together.
What will still be necessary though is getting the original values across the wire. So, I'll probably generate those properties inside of the classes themselves, negating the use of a surrogate serializer. Then, on the client, you will just be able to use your objects like before, and on the server you would notify the objectgraph of the need to fill the original values just before you return them. This might work out very well.

The use of a surrogate is actually what is stopping me from targeting Silverlight, so with a little luck, the changes in the next version will enable the use of Silverlight as well. I'm looking forward to it!

Wednesday, April 23, 2008 11:12:39 AM (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Wednesday, April 16, 2008

I just finished a small sample application that illustrates a client/server application using Entity Framework on the server and just regular objects on the client. The client has custom changetracking and the server is able to attach the graph to a context again. Source can be found at the efcontrib page, and I guess I'm almost ready to do a proper release!

[I used Prism to build the client in a Model View Controller approach. It was a fun exercise and I'm looking forward to seeing that project released.]

The application manages employees and allows for setting a 'teamleader' on an employee: think of 'is managed by'. I thought it would be cool to send that over the wire.

Here is a screenshot of the main view of the application:

image

As you can see, you can 'choose' an employee. When you press that button, you will see another screen where you can enter a lastname. It will fill a grid with employees matching that criteria and allows you to choose from that list.
It is also allowed to 'add an employee'. There are actually 3 types of employees you can add: Mort, Elvis and Einstein.

On the row of teamleader, you can again press the 'choose' button, which will allow you to set a relation between the employee you are editing and another employee.

On the server, there are a few methods like this:

  0   public List<Employee> GetEmployees(string lastNameBeginsWith)
  1   {
  2    using (InheritanceTypeContext context = new InheritanceTypeContext())
  3    {
  4
  5     List<Employee> employees = (from e in context.Person.OfType<Employee>().Include("TeamLeader").Include("TeamMembers")
  6       where e.Lastname.StartsWith(lastNameBeginsWith)
  7       select e).ToList();
  8
  9    
  10     employees.ForEach(p => context.PrepareForSerialization(p)) ;
  11     return employees;
  12    }
  13   }
  14

 

You can see me taking care to call the 'prepareForSerialization' on each graph that I'm returning on line 10.

The client can just use these objects like normal.

 

I'll look into delving into it a bit with a screencast soon.

Wednesday, April 16, 2008 2:55:10 PM (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback

I first wanted to focus on the other aspects of EFContrib, but I finally sat down and finished the last missing piece of EFContrib: full inheritance support for both the server bits and the client bits.

Most work was in the serialization actually, since the surrogate classes need to now also serialize the properties of base types.

I'm working on a sample right now that will show off the system in WPF. But you can check out some of the code in the test project.
This is the domain I'm using:

image

In the following code I'm using it.

  0    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  1    {
  2     var persons = from p in context.Person
  3          select p;
  4     foreach (Person p in persons)
  5      context.DeleteObject(p);
  6
  7     context.SaveChanges();
  8    }
  9
  10    string MsgOnWire = String.Empty;
  11    int id;
  12    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  13    {
  14
  15     Einstein lead = new Einstein { Firstname = "Bill", Lastname = "G" };
  16     context.AddToPerson(lead);
  17
  18     Mort e1 = new Mort { Firstname = "Ruurd", Lastname = "Boeke", Language = "C#", EF=true, WCF=true, WF= true, WPF=true, TeamLeader=lead };
  19     context.AddToPerson(e1);
  20
  21     Elvis e2 = new Elvis { Firstname = "Elvis", Lastname = "Presley", Language = "Java", EF = false, WCF = true, WF = false, WPF = true, TeamLeader = lead };
  22     context.AddToPerson(e2);
  23
  24     context.SaveChanges();
  25     id = e1.PersonID;
  26
  27     MsgOnWire = context.Serialize(e1);  // we'll take mort as the graphroot (no importance)
  28    }
  29
  30    // deserialize
  31    MortClient mClient = MsgOnWire.DeserializeForClient<MortClient>();
  32    mClient.Firstname = "changedAt" + DateTime.Now.ToString();
  33    string nameToCheck = mClient.Firstname;
  34    mClient.EF = false; // mort tends to forget skills
  35
  36    EmployeeClient teamlead = mClient.TeamLeader;
  37
  38    // elvis is a free soul, he can not be managed.
  39    ElvisClient eClient = (ElvisClient) mClient.TeamLeader.TeamMembers.Last();
  40    mClient.TeamLeader.TeamMembers.Remove(eClient);
  41    eClient.TeamLeader = null;
  42
  43    // always add more einsteins in the mix
  44    EinsteinClient einClient = new EinsteinClient { EF = true, WCF = true, WF = false, WPF = false, TeamLeader = teamlead, Firstname = "Albert", Language = "C#", Lastname = "Einstein" };
  45    teamlead.TeamMembers.Add(einClient);
  46
  47
  48    // serialize
  49    MsgOnWire = mClient.SerializeForClient();
  50
  51
  52    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  53    {
  54
  55     // deserialize
  56     Mort m = context.Deserialize<Mort>(MsgOnWire);
  57
  58     context.SaveChanges();
  59    }
  60

Lines 31 to 41 represent the client. For testing purposes I created a copy of the domain with the suffix Client. In normal usage this would obviously not be necessary.
The client remembers all the original values, which allows the server to build up an efficient graph when it is time to attach.

Wednesday, April 16, 2008 11:18:32 AM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Tuesday, April 15, 2008

I'm building a small sample for EFContrib, and thought it would be cool to use the new MVC framework 'Prism' for it. Prism is a new framework currently under development by the patterns and practices group. It is not feature complete and everything might change in the next drop. But, well, it's fun to see such a framework develop and how best to understand it, than by building something simple with it!

I'm trying to do something fairly basic: I have a view that has a button on it. If the button is pressed, a form should popup where we can search for employees. When the search is over, the result should be accessible by my controller.
At the same time though, I know that I'm going to have a detail screen as well with the same button on it. Here the button chooses a teamleader for the employee.

I want to define the command once, but need my controllers to behave differently. It's quite possible that I would be better off just creating two commands (one for the detail screen and one for the employee screen). You could argue that they perform different actions: choose an employee versus choose a teamleader.
But I don't swing that way and I feel it should be possible to have the same command on a lot of buttons and let the appropriate controller deal with it.

In the prism project are a few base classes for commands: the DelegateCommand and also the ActiveAwareDispatchCommand. As far as I can see, they allow a command to be hooked up by multiple views and allow controller to register their interest in them.
I created a static class with my 'ChooseEmployee' command:

 

    public static class EmployeeChooserCommands
    {
        public static ActiveAwareMultiDispatchCommand ChooseEmployee = new ActiveAwareMultiDispatchCommand();
      }

Now, my views couple their buttons to this command in the regular way.

In my definition of MVC a controller is responsible for the logic and thus handles this command.

        protected ActiveAwareDelegateCommand chooseEmployeeCommand;

It defines it's own command and in the ctor hooks it up:

            chooseEmployeeCommand = new ActiveAwareDelegateCommand(Choose, CanChoose);
            // register this instance on the global
            EmployeeChooserCommands.ChooseEmployee.RegisterCommand(chooseEmployeeCommand);

The last line will make this controller react to executions of the command by every source.

This is the pattern that I see in the current Prism reference implementation project.

The fun thing about the ActiveAwareDelegate is the way you can set it as Active and not-Active. If it is not active, it will not be queried for canExecute information and its execute delegate will not be called.

So, what I did, was to let my views implement the IActiveAware interface and throw an event when they lose or get focus. The corresponding controllers react to it in this way:

        void view_IsActiveChanged(object sender, EventArgs e)
        {
            chooseEmployeeCommand.IsActive = view.IsActive;
          }

Setting the command to only be active when the view is active.
Downside here is that if one view is active, it gets to decide on the canExecute result, but all buttons in all views will react to it: clearly not what we want.

So, I feel I'm on the wrong track here. I really miss being able to set some sort of 'affinity' to the RegisterCommand method. I would like to let that method know I'm interested in commands where the source is equal to my view. But then again, maybe I should just create different commands :-)

Tuesday, April 15, 2008 5:50:12 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback