Follow @PDSAInc Bind ObjectDataProvider Method Parameters in WPF - Paul Sheriff's Blog for the Real World

Paul Sheriff's Blog for the Real World

This blog is to share my tips and tricks garnered over 25+ years in the IT industry

Paul's Favorites

Bind ObjectDataProvider Method Parameters in WPF

It is absolutely amazing how much you can do in WPF without writing a line of code. If you take full advantage of the data-binding features in WPF you will find that a lot of the code you used to write to move data from one control to another, or move data from a control on a form and pass it to the method on a class can be completely eliminated!

To illustrate, take a look at Figure 1. This window loads users from your Active Directory, but only loads them once you have typed a letter(s) into the TextBox. This Window has no code behind it at all for loading the users. It uses an ObjectDataProvider to create an instance of a class and call one of its methods. This method takes a single parameter which is the letter(s) of the user name to locate in your active directory. This blog entry will discuss how to build this window and bind the TextBox control to the method parameter of the ObjectDataProvider.

Read AD Users
Figure 1: Retrieve AD Users using an Object Data Provider

Create an AD User Class

First off you need to create a class to hold the data you will retrieve about the user from your Active Directory. Below is a simple class that I created to hold just the Name and the DistinguishedName properties from the user object returned. Feel free to modify this class to return other data.

C#
public class PDSAADUser
{
  public string Name { get; set; }
  public string DistinguishedName { get; set; }
}


Visual Basic 
Public Class PDSAADUser
  Private mName As String
  Private mDistinguishedName As String

  Public Property Name() As String
    Get
      Return mName
    End Get
    Set(ByVal value As String)
      mName = value
    End Set
  End Property

  Public Property DistinguishedName() As String
    Get
      Return mDistinguishedName
    End Get
    Set(ByVal value As String)
      mDistinguishedName = value
    End Set
  End Property
End Class

Create an AD User Collection Class

Next you create a collection class using the Generic List class and creating a list of PDSAADUser objects. In this class is where you create the method to retrieve the list of users from your active directory. Since some companies have many users in their active directory, it is wise to set a property of whether or not to allow all users to be returned. I created a property called AllowAllUsers that I set to false by default so you must pass in at least one letter to the GetUsers method in order to filter the users returned from your active directory. You can initialize this flag to whatever you wish.

Below is a stub of this collection class. You can see the constructor for this class and the AllowAllUsers property and the signature for the GetUsers overloaded method. There are actually two signatures for GetUsers. The first method with only one parameter is the one we are calling from our ObjectDataProvider on this window. It will retrieve the default LDAP Path string from the Active Directory Services built-in to .NET and then pass both that string and the partial name you are searching for to the second GetUsers method. I did this in this sample just to illustrate how to bind a single text box to the ObjectDataProvider. Of course, you could have the ObjectDataProvider call the method with two parameters, you would just have to bind to an LDAP Path string contained in maybe another class that you create. This class could retrieve the LDAP Path from a config file for example.

C#
public class PDSAADUsers : List<PDSAADUser>
{
  public PDSAADUsers()
  {
    AllowAllUsers = false;
  }

  public bool AllowAllUsers { get; set; }

  public PDSAADUsers GetUsers(string partialUserName )
  {
    // Get Default LDAP Path String Here

    // Return users here
  }

  public PDSAADUsers GetUsers(string ldapPath,
                              string partialUserName )
  {
    // Return users here
  }
}

Visual Basic
Public Class PDSAADUsers
  Inherits List(Of PDSAADUser)

  Public Sub New()
    AllowAllUsers = False
  End Sub

  Private mAllowAllUsers As Boolean

  Public Property AllowAllUsers() As Boolean
    Get
      Return mAllowAllUsers
    End Get
    Set(ByVal value As Boolean)
      mAllowAllUsers = value
    End Set
  End Property

  Public Function GetUsers(ByVal partialUserName As String) _
                           As PDSAADUsers
    ' Get Default LDAP Path String Here

    ' Return users here
  End Function
 
  Public Function GetUsers(ByVal ldapPath As String, _
                           ByVal partialUserName As String) _
                           As PDSAADUsers
    ' Return users here
  End Function
End Class

Binding the TextBox to the Object Data Provider

Now, let’s look at how to hook up the TextBox control to the ObjectDataProvider control. First you define the ObjectDataProvider in the <Window.Resources> section of your window as shown below.

<ObjectDataProvider x:Key="ADUsers"
                    ObjectType="{x:Type src:PDSAADUsers}"
                    MethodName="GetUsers">
  <ObjectDataProvider.MethodParameters>
    <x:Static Member="system:String.Empty" />
  </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

Notice that you are having the ObjectDataProvider create an instance of your collection class and call the GetUsers method. Then notice the MethodParameters collection has defined a single parameter. This parameter is defaulted to a string.Empty value.

Now, this is where it gets tricky. What you need to do is to bind the TextBox’s Text property to feed the first parameter of the MethodParameters collection of the ObjectDataProvider. You do this with the following syntax.

<TextBox x:Name="txtPartialName"
         Width="100">
  <TextBox.Text>
    <Binding Source="{StaticResource ADUsers}"
             Path="MethodParameters[0]"
             BindsDirectlyToSource="true"
             UpdateSourceTrigger="PropertyChanged" />
  </TextBox.Text>
</TextBox>

In the <Binding> on the Text property you set the source of the text box to the static resource called ADUsers. This is the key value of the ObjectDataProvider. The Path property is set to the value “MethodParameters[0]”. This tells WPF to bind to the first parameter in the MethodParameters collection. You also need to specify which event will update the MethodParameters collection. In this example the event is when the Text property changes. By firing the PropertyChanged event you are telling the ObjectDataProvider that it should call the method in the MethodName property again and pass in the data that was just passed into the method parameter from the text box.

Summary

You can check out the complete source code to the GetUsers method by downloading the sample (directions below). The GetUser method is just standard active directory retrieval code. The intent of this blog entry was to show you how to perform data-binding between a text box and the method parameters on the ObjectDataProvider. There is no code behind in the WPF Window. The magic of WPF data binding takes care of all the plumbing and calling the methods in your classes. With data binding you can even pass in parameters to those methods from values in your text boxes, or other controls on your windows.

NOTE: You can download the complete sample code (in both VB and C#) at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then " Bind ObjectDataProvider Method Parameters in WPF" from the drop-down.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Posted: Feb 23 2010, 10:25 PM by psheriff | with 7 comment(s)
Filed under: ,

Comments

Vlad Bezden said:

Great article.  I knew how to get data from ObjectDataProvider, but this is a first time I see how to pass value back to the ObjectDataProvider from XAML.

Also should it be Path="MethodParameters[0]"?

Thanks again for great article.

# February 24, 2010 10:32 AM

psheriff said:

Vlad,

Yes, you are right. I changed it in the text, but did not update the source text. The sample code is correct, just a typo when I was writing the article.

Glad you enjoyed it.

Paul

# February 24, 2010 10:37 AM

Shravan said:

Hello, This is a great article! You are passing values from a TextBox control to the ObjectDataProvider. However, I'm trying to do the same using a Menu control where upon selecting a MenuItem, the header property would be sent as the parameter to the ODP. I tried a couple of ways but didn't find them working, Could you please advise. Sample code is as below, Any help would be greatly appreciated.

Thanks,

Shravan

<Menu Name="nmMenu" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" FontSize="12" DockPanel.Dock="Top">

           <Menu.BitmapEffect>

               <DropShadowBitmapEffect/>

           </Menu.BitmapEffect>

           <MenuItem Header="File">

               <MenuItem Header="SNYC12P10650" IsCheckable="True" ToolTip="Production" Click="MenuItem_Clicked">

                   <MenuItem.DataContext>

                       <Binding Source="{StaticResource NMInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"/>

                   </MenuItem.DataContext>

               </MenuItem>

               <MenuItem Header="GPRI12D10217" IsCheckable="True" ToolTip="QA" Click="MenuItem_Clicked">

                   <MenuItem.DataContext>

                       <Binding Source="{StaticResource NMInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"/>

                   </MenuItem.DataContext>

               </MenuItem>

               <MenuItem Header="GPRI12D10219" IsCheckable="True" ToolTip="Dev" Click="MenuItem_Clicked">

                   <MenuItem.DataContext>

                       <Binding Source="{StaticResource NMInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"/>

                   </MenuItem.DataContext>

               </MenuItem>

               <Separator/>

               <MenuItem Header="Close"/>

           </MenuItem>

       </Menu>

# March 10, 2010 7:09 AM

psheriff said:

Shravan,

As far as I know the Menu header does not have access to the bound data. I don't know how to bind to the Header attribute. Now, you could always use a different type of WPF control instead of a menu, and change it to look like a menu. Then maybe you could bind to that control's 'content' property.

Or maybe someone else reading this can chime in here...

Paul

# March 10, 2010 3:08 PM

Raghavendra said:

Hi good article,

i have a query can be bind property to multiple object dataprovider methods.

# October 4, 2010 3:43 AM

psheriff said:

Raghavendra,

I don't think you can hook one property to multiple object data provider methods as you are only allowed one data context. I have not tried it.

Paul

# October 11, 2010 10:02 AM

Philippe GARRAUD said:

Many thanks. I did not know how to get a data context in the Xaml

# January 29, 2011 11:15 AM