My Potential My Passion

You are never given a wish, without also being given the power to make it come true - Richard Bach

Data Reference Binding for Non-WPF stuff

clock November 16, 2008 04:04 by author Sarang

Well I am sure this is sounding weird when the whole world is all over WPF. However, I am going to mention my experience about some cool stuff that exists in the framework which I have been exploring for the past few days.

I had a funny problem to solve (I am sure there will be lots of folks there who might find this a not so interesting post). We all know that WPF has a great deal of support for data reference binding (DRB) and sure it is. However, in my specific problem, I wanted to utilize the cool feature of WPF DRB without really meaning to write a WPF application. So, let's say I am wanting to replace the data binding capability under System.Data with the one under System.Windows.Data. Why??? because of the cool stuff that it has in it!! And when I say cool stuff I am specifically referring to literal expressions that can be provided in the Path property, ValueConverters that can be used to translate/transform value of one object to another, etc.

WPF DRB largely operates over DependencyObject - type of objects and DependencyProperties - add to it a spicy of INotifyPropertyChanged interface. [Do a search on those three key words and there's plenty of material out there that describes the whats and hows of each of those].

Now I am going to describe two scenarios and how to solve them using DRB. Note, there could be parallel frameworks and technologies that may be able to achieve the same thing. The beauty is how much code you would end up writing. And with WPF DRB, you will be amazed.

Scenario 1:

I want to bind a collection of an entity (e.g. Persons) to a generic object like a Table, which is my middle tier object. This middle tier, generic table will be consumed by the presentation layer (could be winforms, webforms, office apps, anthing) to be rendered as a UI table. Moreover, the declarative side of my app would read a value from the DB like:

"<Table Source=PersonsCollection>"

So essentially what we are doing is

1. Taking an object in one format and converting it into another.

2. Whilst it's converted to another format, we are establishing two-way binding between those two objects. If I change a value in either one of these objects, it will automatically change the corresponding value on the other object. So e.g. if, Table.Rows[0].Cells[0].CellValue represents the PersonName. If I change the CellValue in this scenario, it will automatically change the value on Persons[0].PersonName to which this cell is bound to.

My Table class may look like this:

 

[Serializable]

public class Table : DependencyObject, INotifyPropertyChanged

{ 

          private Rows _rows = new Rows(); 

          public Rows Rows

          {

             get { return _rows; }

             set { _rows = value; }

          } 

}

[Serializable]

public class Rows : ObservableCollection<Row>

{} 

[Serializable]

public class Row : DependencyObject, INotifyPropertyChanged

{

            private Cells _cells = new Cells(); 

            public Cells Cells

            {

                get { return _cells; }

                set { _cells = value; }

            }

}

[Serializable]

public class Cells : ObservableCollection<Cell>

{}

[Serializable]

public class Cell : DependencyObject, INotifyPropertyChanged

{

          public string CellValue

          {

                get { return (string)this.GetValue(CellValueProperty); }

                set

                {

                    this.SetValue(CellValueProperty, value);

                    OnPropertyChanged("CellValue");

                }

          }

            public static readonly DependencyProperty CellValueProperty = DependencyProperty.Register(

              "CellValue", typeof(string), typeof(Cell), new PropertyMetadata(""));

}

 

And let's say my Person class and Persons collection class looks like this:

 

[Serializable]

public class Persons: ObservableCollection<IData>

{

}

[Serializable]    

public class Person : IData, INotifyPropertyChanged

{

            private string _pName;

            public string PersonName

            {

                get { return (string)this.GetValue(PersonNameProperty); }

                set

                {

                    this.SetValue(PersonNameProperty, value);

                    OnPropertyChanged("PersonName");

                }

            }

            public static readonly DependencyProperty PersonNameProperty = DependencyProperty.Register(

              "PersonName", typeof(string), typeof(Person), new PropertyMetadata(new Person()));

}

[Serializable]
public abstract class IData : DependencyObject
{}

Before we move ahead here are a quick few things:

1. I am declaring a DependencyObject class - IData (I know it is not an interface). The person class derives from it. And Persons collection is not really a collection of Person object but a collection of IData. Why?? Because I like it that way.

2. Persons collection is of type ObservableCollection - this is a collection class available in the framework and it implements INotifyPropertyChanged.

3. I am declaring DependencyProperties at various places to store values that I am going to use for Binding.

 

Now, assume that I am given an expression as above with some more information as follows:

"<Table Source=Persons>

<Row Source= ".[i]">         //This maps to Persons[i] --> i.e. Person object at position represented by "i"

      <Cell = ".Persons[i].PersonName"/>   //This is the Property inside the Persons[i]

</Row>

</Table>"

 

This is more like a template which defines what data my final table should contain.

So in short we are going to take this template and apply it to the Persons collection and get the Table object out of it.

 

I am not going to paste the whole code here, however, this is what we will do in short:

 

Table t = new Table();





for (int dataElementCount = 0; dataElementCount < PersonCollection.Count; dataElementCount++)

 {

Row r = new Row();

for (int cellCount = 0; cellCount < NoOfCellsRequiredInTheRow; cellCount++)

{

               Cell c1 = new Cell();

               System.Windows.Data.Binding cellbinding = new System.Windows.Data.Binding();

               cellbinding.Source = dc;

               dataRefExpression = template.Rows[rowTemplateCount].Cells[cellCount].DataReferenceExpression.Replace("[i]", "[" + dataElementCount.ToString() + "]"); --> This will be .Persons[0].PersonName for the element "0".

               cellbinding.Path = new System.Windows.PropertyPath(dataRefExpression);

               cellbinding.Mode = BindingMode.TwoWay;

              //// IMPORTANT NOTE 1: We at this instance know the target DependencyObject (Cell) and the DependencyProperty 

             //// (CellValueProperty) on that object.

               BindingOperations.SetBinding(c1, Cell.CellValueProperty, cellbinding);



               r.Cells.Add(c1);

          }

          

         t.Rows.Add(r);

}

That's it and by the end of it you will have your Generic table ready with TwoWay DRB. So change the CellValue representing the PersonName in the generic table and it will automatically change the underlying Persons collection and vice-versa.

 

Scenario 2:

 

The second scenario is something like this. A database value has a expression stored like this

"Global.Customers[i].CustomerName" = "Global.Persons[i].PersonName"

 

This may look simple however, it's really not that simple. Refer to my IMPORTANT NOTE 1 above. The binding to be set successfully requires the target DependencyObject and the DependencyProperty on that object. In this scenario, all I know is the source collection is Persons and Target collection is Customers. However, the expression says "Global.". The reason is to show that the DependencyObject actually lies one level below in the hierarchy this time, so I cannot assume by default that the object corresponding to the "substring" before the first "." (dot) --> Global, is a DependencyObject. So how do we get to the DependencyObject --> Customers[i] and Persons[i]??

Two options that I can immediately think of:

1. Use some smart reflection and take each substring check if it's a DependencyObject then enlist it's dependency properties and see if it is equivalent to the one that we are interested in setting... phew... thinking of it, itself is scary.

 

2. Put WPF DRB to use.

Wow...did I just reduce the above sentence (1) to 1/10 of it's size?? Well the solution that we will see will have an equivalent effect.

 

Here's how I tricked WPF DRB to do what I wanted.

 

I created a dummy class such as:

public class ValueSetter : DependencyProperty , INotifyPropertyChanged

{

        public object Dummy
        {
            get { return (string)this.GetValue(DummyProperty); }
            set
            {
                this.SetValue(DummyProperty, value);
                OnPropertyChanged("Dummy");
            }
        }
        public static readonly DependencyProperty DummyProperty = DependencyProperty.Register(
          "Dummy", typeof(object), typeof(ValueSetter), new PropertyMetadata(new object()));



        public void SetValue(ref ValueSetter vsw2)
        {
            this.Dummy = vsw2.Dummy;
        }

}

And then smarties out there would have guessed what's coming next.

 

I write the same exact DRB code that I used for Table object above for both my Left side and Right side of the above expression --> "Global.Customers[i].CustomerName" = "Global.Persons[i].PersonName"

ValueSetter vsw1 = new ValueSetter();
ValueSetter vsw2 = new ValueSetter();

Binding bx1 = new System.Windows.Data.Binding();

bx1.Path = new System.Windows.PropertyPath(literalExpression1);
bx1.Source = Source1; /////THIS IS YOUR GLOBALS OBJECT
bx1.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(vsw1, ValueSetter.DummyProperty, bx1);



Binding bx2 = new System.Windows.Data.Binding();

bx2.Path = new System.Windows.PropertyPath(literalExpression2);
bx2.Source = Source2; ////THIS IS ALSO YOUR GLOBALS OBJECT
bx2.Mode = BindingMode.TwoWay;

BindingOperations.SetBinding(vsw2, ValueSetter.DummyProperty, bx2);

vsw1.SetValue(ref vsw2);

bx1 = null;
bx2 = null;
vsw1 = null;
vsw2 = null;

 

 

And Bingo!!!! We have achieved what we wanted to.. the Global.Customers[i].CustomerName will now contain the value represented by Global.Persons[i].PersonName!!!

And the reason why this worked is because of the magic of two way binding. Setting a value from VSW2 on VSW1, caused the binding on VSW1 to automatically change (update) the value on Customers[i].CustomerName which would in this case be bound to VSW1.DummyProperty.

 

That does it. I hope this code would be found useful. And uh oh... where is XAML and all that WPF thingi.... surprise.. we are not at all touching it here... we are only using the DRB framework...that goes to prove how cool the WPF DRB framework is. Moreover, at this instance we are assigning a primitive value (string) to another string. You can extend this example by actually writing ValueConverter classes and assigning an instance of those to Binding.Converter property.

 

Lastly... Not even a single line of Reflection!!!  

 

That's all for now... Cheers!!!

 

 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Visual NDepend - Professional: A Must Have!!!

clock September 26, 2008 20:23 by author Sarang

Today's I was exploring the Visual NDepend Tool which is super-effective in analyzing the code base to figure out and control the complexity of the code. This tool is particularly useful for architects or enthusiasts interested in getting an overall picture as well as detailed metrics of the application. I ran this tool on a sample application which uses the Microsoft Windows Workflow Foundation's Rules Engine assemblies.

For the sake of getting maximum information about the capabilities of the NDepend tool, the sample application that I have is just a POC (badly written with no structuring or layering, without comments and a lot of spaghetti code).

There were several interesting things that I saw in the report. I am going to quickly enlist some of the cool things here:

1. Application Metrics

If you would like to get a quick overview of Number of Lines of Code, Classes, Delegate, Interfaces, Values types, Enums, Generic Type definitions, Comments and even IL instructions emitted as result of compilation then check out the simplicity as well as effectiveness of NDepend below:

image

2. Assembly Metrics

Complementing the application metrics is the assembly metrics which does the job of reporting the Types in an assembly, number of types outside the assembly that depend on types within an assembly (Afferent coupling), number of types within the assembly which depend on types outside the assembly (Efferent coupling) that exists in those types, number of internal relationships within assemblies and so on. This is very effective from architectural standpoint to achieve a correct balance of coupling and decoupling and in turn helps to gain a correct balance of performance vs maintenance.

image

 

3. Assembly Dependencies

The assembly dependencies are also highlighted with the aid of a metrics table as well as a simple yet effective diagram as below:

image

 

4. Assemblies Build Order

Many of us know that when visual studio IDE builds a solution, it has to take into consideration the order of construction so that appropriate dependency assemblies are generate first before the other assemblies that consume those. This report section gives a quick idea about the build order of assemblies and again I think this is a simple yet very useful thing from architecture analysis standpoint and identify possible build issues.

image

 

5. CQL Queries and Constraints

This is where the over-whelming part of the tool and reporting starts. NDepend uses a SQL like querying facility to query practically every possible information of the .NET application independently of the .NET language used to write the application. So for example if one would like to get metrics related to code quality or encapsulation or unused/dead code then this is your key.

Here are is an example of the CQL report: (observe the areas highlighted in a red rectangle) The CQL syntax shoots out a warning if the IL instructions exceed 200 or lines of code is > 30, etc. This is lovely stuff.

image

6. Types Metrics

Lastly there is smart types metrics table available that gives quick information on various things like associations between classes, cyclomatic complexity computed on the code, depth in inheritance tree, etc.

image

 

 

Again these are things that I covered from a reporting perspective primarily because finally the outputs of the tool speak how good or bad a tool is. And I believe this is a great tool for architects to keep a visual control (if I may say) on the code base and it's definitely amongst some of the must have dev tools.

I will provide screen shots and more information on the tools GUI which again is very easy to use (feels like using Microsoft office product :) like Word or Excel with Ribbon and the UI components have been well laid out.

There's one thing, however that I would like to see in the tool is some user friendly help system that is context aware (like the visual studio context sensitive help). Also, I am not yet sure but my version of NDepend navigates to online help for every small thing. I haven't yet been able to figure out if there is a local help installed with the tool and if so then how do I make NDepend point to it instead of navigating online.

 

Overall rating 4.5 out of 5!!! cheers!!!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Virtual Tech Days - ASP.NET MVC and ASP.NET 3.5 SP1

clock September 18, 2008 00:59 by author Sarang

Once again, it was most fun interacting with you all wonderful people during the webcast. Thank you for taking time out for attending the VTD sessions.

After a hectic schedule and 2 express sessions on "ASP.NET MVC framework Preview Release" and "What's new for Web Developers in .NET 3.5 SP1", I can relax for a while :)

I really appreciate the good and encouraging feedback that I recevied from some of you. I am sure it not only provisions as an "encouragement booster" but I also take it as a great learning experience at the same time. Every session I do, I have different things to learn and work upon :)

Anyhow, for all those who are interested in downloading the powerpoint slide decks and demos for my sessions...please find it embedded below.

 

Working with ASP.NET MVC Preview Release.zip (365.34 kb)

WebDeveloper.zip (857.27 kb)

Currently rated 3.7 by 3 people

  • Currently 3.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Virtual TechDays - Enhancing Developer Productivity - The LINQ way

clock September 16, 2008 21:58 by author Sarang

Hi! Many thanks to those who attended my session. I know the audio was a problem, however with 700+ enthusiasts being on the same voice bridge, it's always a challenge to get the audio smooth.

Here is the presentation and the demo for the session I did. Please feel free to ping me or comment any feedback that you may have.

VirtualTechDays-LINQ.zip (699.58 kb)

Thanks once again for attending the session.

Cheers!!!

Currently rated 4.8 by 5 people

  • Currently 4.8/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Internet Explorer 8 (beta) Live

clock August 28, 2008 05:05 by author Sarang

And here comes the new version of IE 8, designed to be more reliable, faster and a productivity enabler. It aligns itself with industry standards to provide a "write once and run anywhere" experience. Apart from that, it provides plugging in of search providers and also provides a "visual search" facility. It's going to be exciting to use IE8. I am going to post more on this in a few days.

 

http://www.microsoft.com/windows/internet-explorer/beta/

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


About the author

Hi! My name is Sarang and I am glad you dropped in a visit to my blogsite. I am a tech-savy professional and more often that not, you will find blogs related to latest technology and gadgets. However, you will also find that I have a strong inclination towards Microsoft and Microsoft technology....because we build the best software in the world.

DISCLAIMER:

The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.

RecentPosts

Tag cloud

Category list

Sign in