Monday, March 4, 2013

WPF - ObjectDataProvider in WPF


The ObjectDataProvider allows you to get information from another class in your application. It adds the following features:

• It can create the object you need and pass parameters to the constructor.
• It can call a method in that object and pass method parameters to it.
• It can create the data object asynchronously. (In other words, it can wait until after the window is loaded and then perform the work in the background.)


The ObjectDataProvider, like all data providers, is designed to retrieve data but not update it. In other words, there’s no way to force the ObjectDataProvider to call a different method in the DB class to trigger an update. This is just one example of how the data provider classes in WPF are less mature than other implementations in other frameworks, such as the data source controls in ASP.NET.

In this Example i will show you that how to take input parameter from Textbox and populating the data to DataGrid according to it using ObjectDataProvider. Our method takes a single parameter which is the letter(s) of the Employee name to locate in Employee table.

Let See how can we use ObjectDataProvider in WPF.

Step 1
Download Northwind database from the following link.

Step 2
Attach a Northwind database into MS-SQL server.

Step 3
Create a WPF Application and give solution name as SolObjectDataProvider.

Step 4
Create a New Folder in Solution and give the Folder Name as ORD,it is look like this



Click on Image for Better View

Step 5
Add a Linq to Sql class,Select the ORD folder,right click on Add new Item,select LINQ to SQL classes from installed Visual Studio templates and name it NorthwindDC and click on add button,it is look like this





Click on Image for Better View

Step 6
Open a O/R Designer by double click on NorthwindDC.dbml,it is look like this



Click on Image for Better View



Click on Image for Better View

Visual studio provides an object-relational mapping designer,called the O/R Designer which allows you to visually design the object to database mapping.

Step 7
Create a Employee object that will use LINQ to SQL to map to this table.go to the Server Explorer,select Northwind database,go to the Tables and select Employees table,it is look like this



Click on Image for Better View

Drag and drop Employees table from Server explorer onto the design surface of the O/R Designer,it is look like this



Click on Image for Better View

Step 8
Create a Employee Class for Searching Employee Name from Employee Table using Linq or Lambda Expression,it is look like this
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SolObjectDataProvider
{
    public class Employee
    {
        #region Method

        public IList SearchEmployeeData(String SearchWord)
        {
            IList Query = null; ;
            try
            {
                ORD.NorthwindDCDataContext DC = new ORD.NorthwindDCDataContext();

                if (SearchWord != String.Empty)
                {
                    //// Using Linq

                    //Query = (from Q in DC.Employees
                    //         where Q.FirstName.Contains(SearchWord.Trim())
                    //         select new
                    //         {
                    //             FirstName = Q.FirstName,
                    //             LastName = Q.LastName,
                    //             City = Q.City
                    //         }).ToList();

                    //// Using Lambda Expresion
                    Query= DC.Employees.Where(LE => LE.FirstName.Contains(SearchWord.Trim())).Select(LE => new { FirstName = LE.FirstName, LastName = LE.LastName, City = LE.City }).ToList();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message); 
            }

            return Query;
        }

        #endregion
    }
}


Now Code Behind Part done Let move the Design section.

Step 9
Now add TextBox and DataGrid Control on window,it is look like this
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="7*"/>
        </Grid.RowDefinitions>

        <TextBox x:Name="txtSearch"  Grid.Row="0" Grid.Column="0" Height="25" Width="200" HorizontalAlignment="Left" Margin="10,0,0,0"></TextBox>
        
        <DataGrid x:Name="dgGrid" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding FirstName,IsAsync=True}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding LastName,IsAsync=True}"/>
                <DataGridTextColumn Header="City" Binding="{Binding City,IsAsync=True}"/>
            </DataGrid.Columns>

        </DataGrid>
        
    </Grid>



Click on Image for Better View

Step 10
Add the following namespace reference in window tag,it is look like this 
xmlns:Local="clr-namespace:SolObjectDataProvider"
xmlns:System="clr-namespace:System;assembly=mscorlib"

Using this we can access our classes from this above namespace in XAML.

Finally its look like this
<Window x:Class="SolObjectDataProvider.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Local="clr-namespace:SolObjectDataProvider"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        Title="Object Data Provider" Height="350" Width="525">

</Window>

Step 11
Define the ObjectDataProvider in Window.Resources section in our Window,it is look like this
<Window.Resources>
        <ObjectDataProvider x:Key="ODPEmployee" IsAsynchronous="True" ObjectType="{x:Type Local:Employee}" MethodName="SearchEmployeeData">
            <ObjectDataProvider.MethodParameters>
                <x:Static Member="System:String.Empty" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>

ObjectDataProvider create an instance of Employee class and call the SearchEmployeeData method.The MethodParameters collection has defined a single parameter. This parameter is defaulted to a String.Empty value.

Asynchronous Support
ObjectDataProvider.IsAsynchronous property to true, the ObjectDataProvider performs its work on a background thread. As a result, your interface isn’t tied up while the work is underway. Once the data object has been constructed and returned from the method, the ObjectDataProvider makes it available to all bound elements.

Step 12
Binding the TextBox to the Object Data Provider,it is look like this
<TextBox x:Name="txtSearch"  Grid.Row="0" Grid.Column="0" Height="25" Width="200" HorizontalAlignment="Left" Margin="10,0,0,0" Text="{Binding Source={StaticResource ODPEmployee}, Path=MethodParameters[0], BindsDirectlyToSource=True, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>


In the Text property you set the source of the text box to the static resource called ODPEmployee. 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.

BindsDirectlyToSource - When using a DataSourceProvider derived class (for example a
ObjectDataProvider) setting this property to true will bind to the data
source provider object itself, leaving it false will bind to the data
contained in the data source.

Step 13
Bind this ObjectDataProvider  static Resources in  DataContext Property of DataGrid Control,it is look like this

<DataGrid x:Name="dgGrid" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding}" DataContext="{Binding Source={StaticResource ODPEmployee}}">
</DataGrid>


Run the project.

Output

Click on Image for Better View

Full XAML Code
<Window x:Class="SolObjectDataProvider.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Local="clr-namespace:SolObjectDataProvider"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        Title="Object Data Provider" Height="350" Width="525">
    
    <Window.Resources>
        <ObjectDataProvider x:Key="ODPEmployee" IsAsynchronous="True" ObjectType="{x:Type Local:Employee}" MethodName="SearchEmployeeData">
            <ObjectDataProvider.MethodParameters>
                <x:Static Member="System:String.Empty" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="7*"/>
        </Grid.RowDefinitions>

        <TextBox x:Name="txtSearch"  Grid.Row="0" Grid.Column="0" Height="25" Width="200" HorizontalAlignment="Left" Margin="10,0,0,0" Text="{Binding Source={StaticResource ODPEmployee}, Path=MethodParameters[0], BindsDirectlyToSource=True, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        
        <DataGrid x:Name="dgGrid" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding}" DataContext="{Binding Source={StaticResource ODPEmployee}}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding FirstName,IsAsync=True}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding LastName,IsAsync=True}"/>
                <DataGridTextColumn Header="City" Binding="{Binding City,IsAsync=True}"/>
            </DataGrid.Columns>

        </DataGrid>
        
    </Grid>
</Window>


Download
Download Source Code

1 comment: