Mar 26 2009

Accidental Singletons in Collection-Type Dependency Property

Category: .NET | Dependency Property | SilverlightDavid @ 12:00

Dependency Properties are a unique and powerful feature of WPF/Silverlight though they are normally transparent to you and you will, for the most part, not worry about them.  However, there are times when creating a Custom Dependency property will be the precise solution to your problem.  Sometimes you will need to create a dependency property that is a collection-type.  Now there is a very important point that you need to watch when creating a dependency property of this type, and that is the unintended creation of a singleton value.

Let’s see how this works and how you can resolve the issue.

(Insert here the obligatory creation of a temporary Silverlight application.)

After creating my temp application I created two classes.  The first is a person class.  The second is a Family classes that exposes a Members property that is backed by a dependency property and is of the type List<Person>.

   1:  using System;
   2:  using System.Net;
   3:  using System.Windows;
   4:  using System.Windows.Controls;
   5:  using System.Windows.Documents;
   6:  using System.Windows.Ink;
   7:  using System.Windows.Input;
   8:  using System.Windows.Media;
   9:  using System.Windows.Media.Animation;
  10:  using System.Windows.Shapes;
  11:  using System.Collections.ObjectModel;
  12:  using System.Collections.Generic;
  13:   
  14:  namespace SilverlightApplication1
  15:  {
  16:      public class Family    : DependencyObject
  17:      {
  18:          public static readonly DependencyProperty MembersProperty = DependencyProperty.Register(
  19:              "Bars",
  20:              typeof(List<Person>),
  21:              typeof(Family),
  22:              new PropertyMetadata(new List<Person>()));
  23:          
  24:          #region Properties
  25:   
  26:          public List<Person> Members
  27:          {
  28:              get { return (List<Person>)GetValue(MembersProperty); }
  29:              set { SetValue(MembersProperty, value); }
  30:          }
  31:   
  32:          #endregion
  33:   
  34:      }
  35:   
  36:      public class Person
  37:      {
  38:          #region Properties
  39:   
  40:          public string FirstName { get; set; }
  41:          public string LastName { get; set; }
  42:   
  43:          #endregion
  44:   
  45:          #region Constructors
  46:   
  47:          public Person(string firstName, string lastName) 
  48:          {
  49:              FirstName = firstName;
  50:              LastName = lastName;
  51:          }
  52:   
  53:          #endregion
  54:      }
  55:  }

 

In the application I created a simple method that creates two family objects and adds 3 members to the first and 2 members to the second.  I then populate two variables with the corresponding Count from each of the Member property lists like so.

   1:  private void Button_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      Family fam1 = new Family();
   4:   
   5:      fam1.Members.Add(new Person("David", "Risko"));
   6:      fam1.Members.Add(new Person("Wife", "Risko"));
   7:      fam1.Members.Add(new Person("Kid1", "Risko"));
   8:   
   9:      Family fam2 = new Family();
  10:   
  11:      fam2.Members.Add(new Person("John", "Doe"));
  12:      fam2.Members.Add(new Person("Jane", "Doe"));
  13:   
  14:      int fam1Count = fam1.Members.Count();
  15:      int fam2Count = fam2.Members.Count();
  16:  }

After placing a breakpoint at line 16 I investigated our two count variables.  As you can see from the screenshot below we get an unexpected result where both Family objects show that they have 5 members each.  Our code clearly adds 3 members to the first family and 2 to the second, so how is this happening?

AccidentalSingleton1

The key to this is that we have defined a default value for our dependency property in the PropertyMetadata object when we called the Register method (line 22 in first code block).  Our Member list is a reference type and so therefore the default value set in the PropertyMetadata is not a default value per Family instance but rather is is the default value for all instances of our Family.  This is not the functionality that we are going to want in the vast majority of situations.  We need an instance specific list backing our Members property and fortunately there is a straight forward solution.  The key is to set your property to a new instance of its type in your constructor.  Here is the new code for my Family class constructor that accomplishes this.

   1:  #region Constructors
   2:   
   3:  public Family() : base()
   4:  {
   5:      Members = new List<Person>();
   6:  }
   7:   
   8:  #endregion

Now when we run our application we get the following values in our count variables:

AccidentalSingleton2

As you can see by simply re-initializing our dependency property value in our constructor we get the per instance functionality that we want and need.

Now when your out creating those custom dependency properties for collection-typed values you won’t get caught off guard.

NOTE: After typing this post I found the reference documentation on MSDN that actually covers this from a WPF perspective.  The resolution in WPF is slightly different but still applicable.

Tags: , ,

Mar 16 2009

The Shadow Knows! – The finer Nuisances of the VisualBasic.NET Shadows Keyword

Category: .NET | VisualBasic.NETDavid @ 15:22

I suspect that most people don’t often use the Shadows keyword.  I happened to be using it to develop a custom control because the base class I was inheriting from does not declare one of its properties as Overridable.  My control was inheriting from a StackPanel in Silverlight.  I wanted to limit the type of controls that could be placed inside of my control so I shadowed the StackPanel.Children property, which is of type List(Of UIElement), with a Children property of type List(Of CustomType). 

Initially that seemed to work.  It compiled without error or warning so I thought I was good to go.  Then the UI came up and I realized that things were not what they seemed to be.  The objects that I defined in my XAML for test were showing up, but none of the objects I added programmatically were.  Further more, the collection that was behind my custom property only contained the objects I added programmatically while the property on my StackPanel base contained the items I had defined in XAML.  WHAT?!  How is that?

The difference is in how Shadows works and how the Silverlight runtime was viewing my custom type.  When you shadow a property/method, the original property/method is hidden when your object is viewed as your custom type.  However, if your object, which is of your custom type, is cast to the type of the base class then the base class property becomes visible and is the one that gets accessed.  Let me explain with an example.

I have created three classes. Class A is the base class which B derives from A, and class C derives from class B. Like so…

Public Class A
    ReadOnly Property FirstName() As String
        Get
            Return "A"
        End Get
    End Property

    Overridable ReadOnly Property Lastname() As String
        Get
            Return "1"
        End Get
    End Property
End Class
 
Public Class B
    Inherits A

    Shadows ReadOnly Property FirstName() As String
        Get
            Return "B"
        End Get
    End Property

    Overrides ReadOnly Property Lastname() As String
        Get
            Return "2"
        End Get
    End Property
End Class
 
Public Class C
    Inherits B

    ReadOnly Property FirstName() As String
        Get
            Return "C"
        End Get
    End Property

    Overrides ReadOnly Property Lastname() As String
        Get
            Return "3"
        End Get
    End Property
End Class
 
You will notice that the Firstname property on Class A is not declared as Overridable.  This means that to replace it’s functionality I must declare it as Shadows in my derived class B.  I have purposefully left out the Shadows keyword in Class C to show that VisualBasic.NET implicitly Shadows any properties/methods in the derived class if the name matches the name of a property/method in the base class.
 
Now, here is a quick code snippet for a console app that will demonstrate this nuisance of Shadowing.
 

Sub Main() Dim cClass As New C Console.WriteLine("Typed as C: FirstName {0}, Lastname {1}", cClass.FirstName, cClass.Lastname) 'Typed as C: FirstName C, Lastname 3 Console.WriteLine("Typed as B: FirstName {0}, Lastname {1}", CType(cClass, B).FirstName, _
  CType(cClass, B).Lastname) 'Typed as B: FirstName B, Lastname 3 Console.WriteLine("Typed as A: FirstName {0}, Lastname {1}", CType(cClass, A).FirstName, _
CType(cClass, A).Lastname) 'Typed as A: FirstName A, Lastname 3 Console.ReadKey() End Sub

 

 

 

 

 

 

Notice how the value that is returned for Firstname is the value corresponding to the type by which my object is being accessed.  This correlates to my Silverlight example.  When I was adding items to my custom object programatically I was referencing it as the same type of which it is.  However, when the Silverlight run time was building the UIElement tree it was accessing my item as its base type so the items were added to the base type property, not my custom Shadows property.

So, when it comes to Shadowing, you will want to be aware that referencing your classes as the base type will expose the base types functionality and not the Shadowed functionality.

Fortunately Overrides works differently so that the functionality declared as Overrides on the most derived class will always be run and not the functionality of the base class(es). To verify this try removing the Overrides keyword from Class C.  Now the functionality that is declared as Overrides in Class B will always be accessed for the Lastname property.  You should get the following output to your console.

Typed as C: FirstName C, Lastname 3
Typed as B: FirstName B, Lastname 2
Typed as A: FirstName A, Lastname 2

 

Hopefully you have found this quick excursion into the finer points of Shadowing helpful and the next time you use Shadows you’ll know what to expect from your derived classes.

Tags: ,

Mar 12 2009

Focus on LOB’s in Silverlight 3

Category: .NET | Silverlight | Silverlight 3David @ 10:07

I know there are developers out there looking at Silverlight thinking that it’s just another media delivery platform and that Microsoft is just trying to gain market share over Adobe in this area. However, the truth, I am convinced, is much different.  The overlooked aspect of Silverlight that will make the biggest impact in the Rich Internet Application space is the support for Line-of-Business applications to be developed in Silverlight.

This past Monday The Knowledge Chamber posted an interview with Brad Abrams on Channel 9 in which Brad gives us a few teasers about the LOB support being added to Silverlight 3.0.  In the interview Brad shows us the new project template for a Silverlight project that gives a default design to your Silverlight application and that design will apparently be swappable for other default designs. There is also a short preview of new datagrid features and a new details view control.  He also highlights the new “Deep Link” feature that allows you to access specific places in your Silverlight application via a URI.  The only down part is that we have to wait until MIX09 to see the full feature set, but luckily that’s only another week!

Tags: , ,

Mar 5 2009

No Custom Dependency Property Value Inheritance in Silverlight 2

So I have this cool custom control I am working on in SL2. I was hoping to utilize a custom dependency property that could inherit it’s value from a property on a parent object.  But alas, Microsoft has not provided an easy way to implement custom dependency property value inheritance per this post.  It appears that they created a select few dependency properties that would do this, but due to performance issues they haven’t opened this up to the rest of us yet.

Tags: , ,

Mar 2 2009

Spirituality + Technology

Category: GeneralDavid @ 11:30

OK, so just by the title of this post you can tell that it's not going to be a standard "code post" where I explore some finer points of a .NET class or a specific practice in software development.  But, I hope that if you have time you will read through this article with an open mind and give it some consideration.  Perhaps you will find things that resonate with you or at the least prompt some deeper thinking.

------------------------------------------------------------

There are two things in my life that I have a passion for, though I have much to learn about both. One is technology and the other is Jesus Christ. Lately I have been reflecting on how these two passions intersect in life.

A Brief Overview of My Experience with Both

My passion for technology, particularly computer technology, was developed a bit later in life than for some who have my same profession as a Computer Programmer.  A number of years after of college I was working for a major insurance company in Chattanooga, TN when, around 2002, I was asked to develop a Microsoft Access application to track requests and receipt of medical records for claims that were being managed.  Through this application I became familiar with Visual Basic for Applications and did much work in VBA code.  Shortly after that I began to venture into the world of .NET 1.0 and have worked in each version of the Framework since then.  Most of my experience has been with VB.NET though I have often rewritten or converted parts of C# code and find myself ever more comfortable with that language. (I digress though.) Over the past two years I have been able to develop my own understanding of software development, architecture OOP, Design Patterns and various Best Practices has come quite a long way.

My passion for Jesus Christ has been the the common thread running through the fabric of my life since I was a child.  That is not to say that I am a great spiritual sage.  I find myself often struggling on my spiritual journey.  But, then, that is why God came to earth in the person of Jesus to begin with.  We all find ourselves struggling to live in this life.  We know the pain and suffering, sorrow and grief that is common to everyone on planet earth.  And we all, at some point in time, recognize that the world is not as it should be.  The question is, who is going to fix it? It is my belief that Jesus Christ in the only one who can fix this world and the people who live in it.  Humanity itself clearly cannot fix this world as evidenced my the manifold wars and catastrophes throughout history. Rather, the one who must fix the world and restore it to its original perfection is the one who made it in the first place, namely God, in the person of Jesus. Not only do we find in Jesus the resolution to the problems with the world and ourselves, but we also find in Him the absolute purpose of all that exists in this world, including technology.  This then is where my two passions intersect and where I find my greatest purpose and joy in life.

The Intersection of Technology and Spirituality

Technology is such a wonderful and intriguing area which has much potential to do good in the world, but also much potential for evil.  It is only when we utilize and extend technology in accordance with God's intention for it, that we will avoid the pitfalls of technology and succeed in spreading good throughout the world by the means of technology.  When we acknowledge the inseparable connection between technology and the One who created it, we will find ourselves driven to use and develop technology according to those purposes that He created it for.  For me that means that I find great satisfaction in working on applications used by local law enforcement and court systems because they are working to bring about justice in society.  They strive to defend and protect those who are persecuted and those who have become victims in criminal activity.  This is inline with God's own nature as he revealed himself to us in Jesus, for he teaches us to "act justly and to love mercy and to walk humbly with God".

There are of course many other aspects to the intersection of spirituality and technology and hopefully in the course of time I will be able to explore some of them on this blog.

Tags: