ASP.NET MVC First Impressions

February 21, 2010 19:06 by wjchristenson2

Today I decided to make a small ASP.NET MVC application which would add, edit, delete, and list US states which resided in a SQL Server Express database.  I am a veteran in ASP.NET Web Forms development, so I wanted to see what MVC is like.  I create business objects/models everyday, so understanding models was easy enough.  The tricky part for me was creating and understanding how controllers and views interact with each other.

First Impressions:
1)  I liked the clean separation between controller/view/models.  Basically this is required when using MVC.  I’ve already been accustomed to separating layers, so this wasn’t new to me, but seeing how the MVC Framework has this built in was refreshing.
2)  When I created a new MVC Web Application, it automatically prompted to create a Test project.  I thought that was pretty neat.  I’m not experienced in creating automated test yet, but I’m sure I’ll get there soon and just seeing the parallelism with MVC and testing was impressive.
3)  REST (Representational State Transfer) URLs was interesting.  Apparently you can configure how requests are mapped to controllers in the Global.asax.  I didn’t get into this much as I took the defaults, but simply editing a state looked like such: “/states/Edit/1”.  No more mapping to a template/resource.
4)  You can generate a view straight from the controller by right-clicking when you return an ActionResult.  Visual Studio will then prompt/ask you what kind of view you want to make and you can also have it create a strongly typed view so that you can access the model’s properties.  So the framework can assist in starting a view pretty quickly for you.
5)  Not having view state and post backs was really nice.  The rendered HTML was very clean.
6)  I was confused at times as to how the framework knew what to pass to controller routines on a form post and also how id’s work.  What if you have more than 1 property that makes up the id?  I imagine this would come with time.

Overall I enjoyed the initial experience and it seemed very structured.  I feel that one day doesn’t do it justice as MVC is a bit more complex than web forms.

Helpful Resources:
1)  Scott Guthrie’s NerdDinner.com Chapter:  Scott Guthrie wrote a chapter in Professional ASP.NET MVC 1.0 in which he walks you through step-by-step in creating an MVC web application.  You can download the chapter in PDF and also download the source code if needed.
2)  Simple E-Commerce Storefront Application: This is another Scott Guthrie example, however this example has some nice architecture diagrams that go along with it to explain what’s going on a bit more.

MVCTest_Soln.zip (891.39 kb)

ASP.NET MVC Overview Part 1 (General ASP.NET MVC Overview)
ASP.NET MVC Overview Part 2 (Advantages of MVC and Web Forms)
ASP.NET MVC First Impressions


Currently rated 5.0 by 1 people

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

ASP.NET MVC Overview Part 2

February 14, 2010 13:36 by wjchristenson2

In Part1, I discussed the basics of what the MVC pattern is and how Microsoft has incorporated MVC into ASP.NET.  In this segment, I am going to discuss some general advantages of ASP.NET Web Forms and ASP.NET MVC.  Neither flavor of ASP.NET will be the superior choice in all circumstances.  Therefore knowing the advantages to each will help.

I’ve found through my development career that there’s never a right or wrong way to do something.  Scott Guthrie posted recently the following which is very true, “Great developers using bad tools/frameworks can make great apps.”  The same principal applies to bad developers using great tools/frameworks… inevitably they will create bad applications.  Just because one framework may shine better in certain situations may not mean its better.  If the developers using the superior technology cannot grasp or develop it properly, its full potential will not be realized.  So keep these principals in mind when evaluating the two.

Advantages of ASP.NET MVC
1) Separation of model, view, controller results in reduction of complexity, promotes parallel development, and easier to maintain.
2) Enables full control over rendered HTML (leaner html rendering).
3) Works much better with automated testing as all core contracts are interface based.  You can run unit-tests without having to run the controllers under an ASP.NET process.
4) Does not use view state or postbacks (no view stage = quicker load times).
5) Framework is very extensible and pluggable.
6) Supports existing markup (aspx, master pages, ascx, inline expressions).
7) Supports existing session, caching, authentication, etc.
8) Easy integration with javascript frameworks.
9) Follows the design of a stateless web.


Advantages of ASP.NET Web Forms
1) Commonality between windows forms development in that it uses the event model.
2) Usage of view state and server forms helps manage state more easily.
3) Promotes RAD more so than MVC as more controls/components are available.
4) Less complex than MVC and generally requires less code.
5) More mature as it’s been around since the 1990’s.

ASP.NET MVC Overview Part 1 (General ASP.NET MVC Overview)
ASP.NET MVC Overview Part 2 (Advantages of MVC and Web Forms)
ASP.NET MVC First Impressions


Be the first to rate this post

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

ASP.NET MVC Overview Part 1

February 9, 2010 21:35 by wjchristenson2

Traditionally there has been only one approach to develop ASP.NET web applications; web forms.  Lately I’ve been hearing a lot of hype wrapped around this thing called MVC and the fact that it can be used as an approach to develop ASP.NET applications.  What is MVC?  MVC stands for Model-View-Controller.  It is a design pattern which separates an application into 3 logical tiers: domain, input, and presentation.  This isolation between layers yields independent development, testing, and maintenance of each.

Model – The model can be thought of as the business layer.  It performs application logic and is used to maintain the state of the application typically in a database.

View – A view is a component that is used to display the UI which can often be a direct representation of the model’s state.  For an example, the model may return a collection of workers from the database.  The View could display the workers in a GridView/DataGrid.

Controller – The controller ultimately handles and responds to user interaction.  It works with the model based on what the user desires and then renders the appropriate view accordingly.

The ASP.NET MVC Framework is Microsoft’s stab at at creating an ASP.NET programming environment that is centered around the MVC pattern.  So how is the request model different between MVC and traditional web forms?  An ASP.NET web form uses the postback to relay the request and the page’s code behind handles it.  In ASP.NET MVC, REST is used to communicate the request and MVC is used to process it.

REST stands for Representational State Transfer.  In ASP.NET MVC, instead of mapping URLs to ASPX files stored on disk you are mapping URLs to controllers (classes).  The controller will handle what view to render back to the end-user.

ASP.NET MVC Overview Part 1 (General ASP.NET MVC Overview)
ASP.NET MVC Overview Part 2 (Advantages of MVC and Web Forms)
ASP.NET MVC First Impressions


Be the first to rate this post

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

Configure WCF Service – Reuse Collection Types Issue

December 14, 2009 14:22 by wjchristenson2

In VS 2008, there is a problem with reusing collection types when you configure a WCF service and wish to “Reuse types in all refrenced assemblies”.  If you want to pass collections around via your WCF service, a Visual Studio will create a proxy class for each collection type regardless whether your collection type is included within referenced assemblies or not.  I will show you how to bypass this shortcoming.

First, locate the Reference.svcmap file for the WCF service reference you are having problems with.  If you can’t see it, ensure your project  has “Show All Files” enabled.  If you open the Reference.svcmap, you’ll find that it is written in XML.  Locate the CollectionMappings node.  Within CollectionMappings, add your collection type so when you update your service reference, it recognizes it as a known type and will not generate a proxy class for you.  Hope this helps.


   1:  <CollectionMappings>
   2:      <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
   3:      <CollectionMapping TypeName="WpfApplication1.Objects.MyCollection" Category="List" />
   4:  </CollectionMappings>

Be the first to rate this post

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

Fiddler - Inspecting WCF Binary Encoded Messages

November 25, 2009 08:57 by wjchristenson2

Fiddler is the tool of choice when it comes to inspecting WCF messages that utilize an HTTP transport.  In a previous post I mentioned that HTTP WCF messages should be in encoded in a binary format to decrease their size.  The problem you run into when encoding your WCF messages is that when Fiddler attempts to inspect an encoded message, it’s not in a readable format.  To resolve this limitation, you can download a free plug-in which will add an inspector to Fiddler to decode binary WCF message.  Using this new inspector, you can inspect binary encoded WCF messages freely from within Fiddler.

http://code.msdn.microsoft.com/wcfbinaryinspector



Be the first to rate this post

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

Silverlight 3 WCF Binary Message Encoding

October 14, 2009 13:29 by wjchristenson2

Silverlight 3 offers us some new features when it comes to WCF web services.  In Silverlight 2, BasicHttpBinding was the only supported binding.  This essentially encodes your serialized objects in clear text and sends them over an HTTP transport.  Because the objects were sent as clear text, the message size could get out-of-hand.  When sending data across HTTP/Internet, you obviously want to decrease the size as this will improve performance of your client application.  Silverlight 3 offers the ability to create custom bindings which support the ability to encode your WCF web service messages as a binary format.

Binary encoding offers some serious performance gains over text encoding.  Personally I’ve seen 30% – 40% reduction in message size between the server and client when binary encoding is enabled.  Keep in mind that binary encoding is a WCF-specific feature.  Therefore if you have heterogeneous technologies wanting to consume your service, you’ll need to stick with BasicHttpBinding.  Here is an example of how to enable binary encoding for your WCF service:


   1:  <bindings>
   2:     <customBinding>
   3:        <binding name="binaryHttpBinding">
   4:           <binaryMessageEncoding />
   5:           <httpTransport />
   6:        </binding>
   7:     </customBinding>
   8:  </bindings>
   9:   
  10:  <endpoint address="" binding="customBinding" bindingConfiguration="binaryHttpBinding" contract="MyService" />

Be the first to rate this post

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

Introduction to SQL Server Change Tracking

October 3, 2009 12:39 by wjchristenson2

An all too familiar challenge of today’s applications is to support the mobile user.  A mobile user is not always guaranteed to have a connection to the home office.  They need an application that can support both offline and online connection states.  An application that is occasionally connected is often referred to as an “Occasionally Connected Application” (OCA).  OCAs will often work offline and when brought online will execute synchronization processes.  In this blog, I’ll briefly introduce some nice features included with SQL Server 2008 Change Tracking.

SQL Server has had replication features for quite some time now.  I’m by no means an expert when it comes to SQL Server Transactional replication, but personally I’ve found it difficult to setup, troubleshoot, customize, and unable to easily communicate across N-Tier application environments.  In the past, the next option from replication was to create our own SQL synchronization engines utilizing triggers, timestamp columns, tombstone tables, etc to track database changes on the client and server and then synchronize up the differences.  There are some problems with this solution.  First glaring issue to me is the use of triggers.  Triggers cause transactions to take longer to commit and cause blocking issues.  So basically performance and storage issues result from this solution prior to SQL 2008 Change Tracking.  SQL 2008 now provides a new feature which is available in all versions: SQL Change Tracking. 

SQL Server Change Tracking Advantages/Features:

1)  Easy to Setup.  It does not require timestamp columns, tombstone tables, triggers, etc.  You can simply script or use SQL Management Studio to turn on SQL Change Tracking for a database and then what tables you want to track changes on.

2)  Better Performance.  Changes are tracked at commit time rather than when DML operations occur.  What this basically means is transactions run quicker and this also helps with blocking issues.

3)  Minimal Disk Space Costs.  Change Tracking stores changes in SQL system tables and the disk space cost is minimal.

4)  Integrates with the .NET Sync Framework.  If you are using the .NET Sync Framework to develop your OCA, then .NET/Visual Studio has some nice features that are at the developer’s disposal.

5)  Synchronize with other DB Platforms.  SQL Change Tracking runs independently from other databases.  So if your server is running an Oracle DB and you want to run SQL Compact on your client with Change Tracking enabled, it will support that just fine.  Changes on the client are tracked independently of the server and obviously vice versa.

6)  Packaged Functions.  SQL Server comes with packaged functions that are used to query the SQL Change Tracking system tables to acquire incremental changes.

7)  Auto Clean Up.  When SQL Change Tracking is enabled for a database, you can specify when change history will be purged automatically for you.

8)  Column or Entire Row.  You can enable change tracking to record that an entire row/record had something changed in it or you can even track down to what column was changed to limit the amount of data changes returned when querying for incremental changes.

Example 1 - Turn on SQL Change Tracking for a Database:


   1:  ALTER DATABASE [AdventureWorks2008] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 365 DAYS, AUTO_CLEANUP = ON);
   2:  GO

Example 2 – Turn on SQL Change Tracking for a Table:


   1:  ALTER TABLE HumanResources.[Department] ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = OFF);
   2:  GO

Example 3 – Return Incremental Table Inserts:


   1:  DECLARE @sync_last_received_anchor BIGINT, @sync_new_received_anchor BIGINT;
   2:   
   3:  SELECT @sync_last_received_anchor = CHANGE_TRACKING_CURRENT_VERSION();
   4:   
   5:  INSERT INTO [HumanResources].[Department] (Name, GroupName, ModifiedDate) VALUES ('Test1', 'My Group', GETDATE())
   6:  INSERT INTO [HumanResources].[Department] (Name, GroupName, ModifiedDate) VALUES ('Test2', 'My Group', GETDATE())
   7:  INSERT INTO [HumanResources].[Department] (Name, GroupName, ModifiedDate) VALUES ('Test3', 'My Group', GETDATE())
   8:   
   9:  SELECT @sync_new_received_anchor = CHANGE_TRACKING_CURRENT_VERSION();
  10:   
  11:  --return inserts
  12:  SELECT dept.*
  13:  FROM [HumanResources].[Department] AS dept 
  14:      INNER JOIN CHANGETABLE(CHANGES [HumanResources].[Department], @sync_last_received_anchor) CT ON CT.[DepartmentID] = dept.[DepartmentID]
  15:  WHERE (CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_CREATION_VERSION <= @sync_new_received_anchor)

Be the first to rate this post

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

ExecuteNonQuery with “GO” Separators

September 25, 2009 08:26 by wjchristenson2

If you’ve ever tried to run a collection of SQL batches via the .NET DbCommand.ExecuteNonQuery method, you probably received an error similar to the following: “Incorrect Syntax near ‘GO’ …”.  DbCommand.ExecuteNonQuery is intended to execute a single SQL batch statement against a database.  The “GO” separator is a command that is used/understood by SQL Server Query Analyzer and Query Editor utilities to separate out SQL batches when ran.

There has been some workarounds that I’ve seen that involve regular expressions and string manipulation/splitting to break out the script with “GO” separators into a collection of SQL statements and run them each individually.  This can work, but you will run into situations where commented areas will contain the “GO” statement and other problems can/will arise.  Such situations would cause the workaround to fail.

The proper way to run scripts with the “GO” separator is to employ SQL Server Management Objects (SMOs).  Microsoft’s SQL Server 2008 Feature Pack contains links to download/install the SMO assemblies (.NET Framework object model) .  Developers can use SMOs to perform SQL Server management routines through their .NET application code.

Steps to Use SMOs:

1) Download and Install SMOs - Download the SQL Server Management Objects found on this page.  Run the installation package.  If you are running SQL Server 2005, you may need to search for the 2005 version as the link I gave is for 2008.

2) Add references - After the SMOs are installed,  we’ll need to add references to them in our project.  The SMO assemblies should appear under your .NET tab when adding references to your project.  If you can’t  find them there, the assemblies were installed to “C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies” for me.  To run scripts with “GO” statement, we’ll need references to the following DLLs:
  a) Microsoft.SqlServer.ConnectionInfo.dll
  b) Microsoft.SqlServer.Management.Sdk.Sfc.dll
  c)  Microsoft.SqlServer.Smo.dll

3) Import the required namespaces and execute your SQL script with “GO” statements like below:


   1:  Imports System.Data.SqlClient
   2:  Imports Microsoft.SqlServer.Management.Smo
   3:  Imports Microsoft.SqlServer.Management.Common
   4:   
   5:  Class Window1
   6:   
   7:      Public Sub ExecuteSqlStatements(ByVal connectionString As String, ByVal sqlStatements As String)
   8:          If Not String.IsNullOrEmpty(sqlStatements) Then
   9:              Using mySqlConnection As SqlConnection = New SqlConnection(connectionString)
  10:                  Dim mySqlServer As Server = New Server(New ServerConnection(mySqlConnection))
  11:                  mySqlServer.ConnectionContext.ExecuteNonQuery(sqlStatements)
  12:              End Using
  13:          End If
  14:      End Sub
  15:   
  16:  End Class

SqlBatchExecNonQuery_Soln.zip (965.09 kb)


Be the first to rate this post

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

Silverlight Custom Content Control with Events

July 6, 2009 13:40 by wjchristenson2

In an earlier post, I wrote about how to develop a Silverlight custom content control.  Since then I’ve received inquiries as to how to add events to it.  More specifically, how can we add interactivity to the control and have the control raise events which can be handled by the consumer of our control.

Step 1: Add Template UI Elements to Receive User Interaction

In the previous post, I described how to create a generic.xaml file to house our templated control UI (style).  In this example, I am going to create a close HyperlinkButton and raise a close event.  Here’s our style which is defined in the generic.xaml file.  Take not of our new hlbClose HyperlinkButton (line 34).


   1:  <ResourceDictionary 
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:local="clr-namespace:ContentControlExample.Controls">
   5:   
   6:      <!-- CustomContentControl -->
   7:      <Style TargetType="local:CustomContentControl">
   8:          <Setter Property="Background" Value="Transparent" />
   9:          <Setter Property="Foreground" Value="Black" />
  10:          <Setter Property="BorderBrush" Value="Transparent" />
  11:          <Setter Property="BorderThickness" Value="0" />
  12:          <Setter Property="HorizontalAlignment" Value="Stretch" />
  13:          <Setter Property="VerticalAlignment" Value="Stretch" />
  14:          <Setter Property="HorizontalContentAlignment" Value="Left" />
  15:          <Setter Property="VerticalContentAlignment" Value="Top" />
  16:          <Setter Property="Template">
  17:              <Setter.Value>
  18:                  <ControlTemplate TargetType="local:CustomContentControl">
  19:                      <Border Background="White" BorderBrush="#87AFDA" BorderThickness="1">
  20:                          <Grid>
  21:                              <Grid.RowDefinitions>
  22:                                  <RowDefinition Height="Auto" />
  23:                                  <RowDefinition Height="*" />
  24:                              </Grid.RowDefinitions>
  25:                              
  26:                              <Border Grid.Column="0" Grid.Row="0" Background="#D4E6FC" BorderThickness="0,0,0,1" BorderBrush="#87AFDA">
  27:                                  <Grid>
  28:                                      <Grid.ColumnDefinitions>
  29:                                          <ColumnDefinition />
  30:                                          <ColumnDefinition Width="20" />
  31:                                      </Grid.ColumnDefinitions>
  32:                                  
  33:                                      <ContentControl Grid.Column="0" Content="{TemplateBinding Header}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Foreground="#224499" FontWeight="Bold" FontFamily="Arial" FontSize="12" Margin="3,3,3,3" />
  34:                                      <HyperlinkButton x:Name="hlbClose" Grid.Column="1" Content="[X]" />
  35:                                  </Grid>
  36:                              </Border>
  37:                              <ContentControl Grid.Column="0" Grid.Row="1" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" FontFamily="Arial" FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}" Foreground="{TemplateBinding Foreground}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
  38:                          </Grid>
  39:                      </Border>
  40:                  </ControlTemplate>
  41:              </Setter.Value>
  42:          </Setter>
  43:      </Style>
  44:  </ResourceDictionary>

Step 2: Get a Handle to Template UI Elements

Once we have our control UI looking the way we want it, the next step is to get a handle to our HyperlinkButton and add a handler for its click event.  When the user clicks the HyperlinkButton, we want to raise our control’s Close event.  The trick is to override the OnApplyTemplate of our control and get our handle to the HyperlinkButton using the GetTemplateChild method.  The GetTemplateChild method accepts the id/name of the control we are looking for.  It traverses the visual tree and returns a DependencyObject if found.  Below I show how we can do this:


   1:  Public Class CustomContentControl
   2:      Inherits ContentControl
   3:   
   4:      Private _hlbClose As HyperlinkButton
   5:   
   6:      Public Shared ReadOnly HeaderProperty As DependencyProperty = DependencyProperty.Register("Header", GetType(UIElement), GetType(CustomContentControl), Nothing)
   7:      Public Event Close(ByVal sender As CustomContentControl)
   8:   
   9:      Public Property Header() As UIElement
  10:          Get
  11:              Return DirectCast(Me.GetValue(CustomContentControl.HeaderProperty), UIElement)
  12:          End Get
  13:          Set(ByVal value As UIElement)
  14:              Me.SetValue(CustomContentControl.HeaderProperty, value)
  15:          End Set
  16:      End Property
  17:   
  18:      Public Sub New()
  19:          MyBase.New()
  20:          Me.DefaultStyleKey = GetType(CustomContentControl)
  21:      End Sub
  22:   
  23:      Public Overrides Sub OnApplyTemplate()
  24:          MyBase.OnApplyTemplate()
  25:          _hlbClose = DirectCast(GetTemplateChild("hlbClose"), HyperlinkButton)
  26:          AddHandler _hlbClose.Click, AddressOf hlbClose_Click
  27:      End Sub
  28:   
  29:      Private Sub hlbClose_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
  30:          RaiseEvent Close(Me)
  31:      End Sub
  32:  End Class

Step 3: Raise Control Events

Now that we have acquired a handle to our HyperlinkButton and also have added a handler for its click event, all we have to do now is raise our control’s Close event when the HyperlinkButton is clicked.  The control consumers can handle the close event if they wish.


   1:      Private Sub hlbClose_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
   2:          RaiseEvent Close(Me)
   3:      End Sub

ContentControlExample_Soln.zip (627.32 kb)


Currently rated 5.0 by 2 people

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

Get Child, Parent, or Children Objects in Silverlight

June 17, 2009 18:10 by wjchristenson2

As a programmer, you may have situations where you need a handle to a control to set its property programmatically.  Pretty simple right?  Let’s add some complexity.  What if you are not guaranteed to know exactly where the control resides.  Is it in our Grid at child index 0 or is it in a StackPanel within the Grid?  What if we want to set the background of all Canvas objects on our page to Transparent?

The Silverlight API provides the VisualTreeHelper class to assist with the traversal of the visual object tree.  Silverlight has a logical and visual object tree.  The visual tree is a subset of the logical object tree and is only populated by objects that have rendering implications.  In a general sense, a collection class would not be included in the visual tree however the Grid you are using as your LayoutRoot of your page would be.  The VisualTreeHelper class has 3 methods to assist with the visual object tree: GetChild(), GetChildrenCount(), GetParent().  Their names are self-descriptive and what I’d like to do is create a few recursive helper methods/extensions to these methods that are a bit more powerful.


Helper Method #1: GetParentObject

This method returns the first parent of a given type and/or name of an object’s parent hierarchy.  For instance, let’s say you know that our StackPanel resides somewhere in the bowels of a Grid named LayoutRoot.  To get a handle to LayoutRoot we could do the following:


   1:  Dim g As Grid = GetParentObject(Of Grid)(myStackPanel, "LayoutRoot")

Helper Method #2: GetChildObject

This method returns the first child of a given type and/or name of an object’s child hierarchy.  So let’s take the inverse of the above.  We have a StackPanel named myStackPanel that resides somewhere beneath our Grid LayoutRoot.  The get the handle to myStackPanel we could do the following:


   1:  Dim sp As StackPanel = GetChildObject(Of StackPanel)(Me.LayoutRoot, "myStackPanel")


Helper Method #3: GetChildObjects

This method returns a list collection of all children of a given type and/or name of an object’s child hierarchy.  So let’s say we want all rectangles which reside somewhere on our page.  Again, our page has a Grid named LayoutRoot.  We could get a list collection of all rectangles on the page by making the following call:


   1:  Dim rectangles As List(Of Rectangle) = GetChildObjects(Of Rectangle)(Me.LayoutRoot)


Helper Methods

Below is the actual methods’ code.  I’m also attaching my zipped test solution.


   1:  Module Common
   2:      ''' <summary>
   3:      ''' Navigates up the object's parent hierarchy and returns the first parent match of the specified type and/or object name.
   4:      ''' </summary>
   5:      ''' <typeparam name="T"></typeparam>
   6:      ''' <param name="obj"></param>
   7:      ''' <param name="name"></param>
   8:      ''' <returns></returns>
   9:      ''' <remarks></remarks>
  10:      Public Function GetParentObject(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As T
  11:          Dim parent As DependencyObject = VisualTreeHelper.GetParent(obj)
  12:   
  13:          While parent IsNot Nothing
  14:              If TypeOf parent Is T AndAlso (CType(parent, T).Name = name Or String.IsNullOrEmpty(name)) Then
  15:                  Return CType(parent, T)
  16:              End If
  17:   
  18:              parent = VisualTreeHelper.GetParent(parent)
  19:          End While
  20:   
  21:          Return Nothing
  22:      End Function
  23:   
  24:      ''' <summary>
  25:      ''' Recursively searches an object's child hierarchy and returns the first child match of the specified type and/or object name.
  26:      ''' </summary>
  27:      ''' <typeparam name="T"></typeparam>
  28:      ''' <param name="obj"></param>
  29:      ''' <param name="name"></param>
  30:      ''' <returns></returns>
  31:      ''' <remarks></remarks>
  32:      Public Function GetChildObject(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As T
  33:          Dim child As DependencyObject = Nothing, grandChild As T = Nothing
  34:   
  35:          For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
  36:              child = VisualTreeHelper.GetChild(obj, i)
  37:   
  38:              If TypeOf child Is T AndAlso (CType(child, T).Name = name Or String.IsNullOrEmpty(name)) Then
  39:                  Return CType(child, T)
  40:              Else
  41:                  grandChild = GetChildObject(Of T)(child, name)
  42:                  If grandChild IsNot Nothing Then Return grandChild
  43:              End If
  44:          Next
  45:   
  46:          Return Nothing
  47:      End Function
  48:   
  49:      ''' <summary>
  50:      ''' Recursively searches an object's child hierarchy and returns the all children that are of the specified type and/or object name.
  51:      ''' </summary>
  52:      ''' <typeparam name="T"></typeparam>
  53:      ''' <param name="obj"></param>
  54:      ''' <param name="name"></param>
  55:      ''' <returns></returns>
  56:      ''' <remarks></remarks>
  57:      Public Function GetChildObjects(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As List(Of T)
  58:          Dim child As DependencyObject = Nothing, childList As List(Of T) = New List(Of T)
  59:   
  60:          For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
  61:              child = VisualTreeHelper.GetChild(obj, i)
  62:   
  63:              If TypeOf child Is T AndAlso (CType(child, T).Name = name Or String.IsNullOrEmpty(name)) Then
  64:                  childList.Add(CType(child, T))
  65:              End If
  66:   
  67:              childList.AddRange(GetChildObjects(Of T)(child))
  68:          Next
  69:   
  70:          Return childList
  71:      End Function
  72:  End Module

VisualTreeHelper_Soln.zip (589.38 kb)


Be the first to rate this post

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