Using WCF Data Services in WPF applications January 22, 2012
Posted by fofo in C#, Visual Studio 2010, VS 2010, WCF Service, WPF, XAML.Tags: ODATA, POX, SOAP
add a comment
In this post I will provide you with hands-on examples on how to retrieve data from a WCF Data Service and bind the data to WPF data bindable controls that reside inside a WPF window.The client application in this case will be a WPF application again.
I do not know how familiar people are with WCF Data Services.This technology was formerly known as ADO.Net Data Services,codename -”Astoria”. In these days we all come across applications that do not just use ADO.Net code to fetch data over the network from an SQL Server database.Applications use data services to find and manipulate data on the web.We can call this service that lives somewhere on a web server and pass it a message and then it is the service’s job to complete the task and send back to the client application a result. The client application could be a Windows Form application, a WPF application,Silvelight an Ajax enabled web page e.t.c The service certainly does not care who the client is.You call the service the same way in all those technologies.In a nutshell the goal of WCF Data Services is to create a middle tier and then easily consume it from various clients both Internet and windows clients.WCF Data Services use REST (Representation State Transfer). REST thinks of the the web as a collection of resources. Resources could be Text,images,XML. Resources are identified by URIs.A URI looks like as http://www.mysite.com/Customers. We can use HTTP verbs to access resources.Those verbs are GET,POST,PUT,DELETE. Under the hood WCF Data Services use OData (Open Data Protocol) that helps to expose data as resources that are addressable by URIs.
In Web services, data is transmitted via POX (plain old XML).Having said that, it becomes clear that we do not the added layer that is called SOAP. WCF Services use SOAP, web services use SOAP.Not all platforms support SOAP.If you use REST it is much easier to access services. Bear in mind that not all services need support for transactions,security,reliability.All the functionality of WCF Data Services when we talk about the .Net platform resides in the System.Data.Services dll.In order to create a WCF data service you need to create a data model based on entities. For example we can use Entity Framework for relational data.Obviously we can use a custom LINQ provider for other data sources. In those models each entity has a unique URI.
Let’s move on with our hands-on examples.Ι will provide several examples. In the first one I will use a custom data object. In the second one I will use a database.
I assume that you have access to a version of SQL Server and AdventureWorkLT database.
If you do not, you can download and install the free SQL Server Express edition from here. If you need the installation scripts for the sample AdventureWorksLT database, click here . We will use our WCF service to get data from the the Customers table of the AdventureWorksLT database.
In order to create a WCF Data Service , first we need to create the Entity Data Model and then add a new item that is based on the WCF Data Service template.
Then we need to point to the Entity Data Model and grant read/write access to entities
1) Launch Visual Studio. I will be using Visual Studio 2010 Ultimate edition. I will be using C# as the development language.
2) Add a WPF application to your solution. Give it a meaningful name. I named mine WpfWcfDataServiceApplication.
3) Add an empty ASP.Net Web application to your solution.This application will host the WCF Data Service.Give it a meaningful name.I have named mine HostWCFDataService
4) The next step is to create the entity data model.Add this item to your ASP.net Web application project.Add an ADO.NET Entity Data Model. Ι have named mine AdventureWorksLT.edmx. I will generate the model from the database. As you see there is a wizard that helps you complete the steps. In the next step of the wizard you need to point to the database. Create a new connection to the database if you do not have one already and click Next.Select all the objects in the Tables and click Finish.
In the Entity Model Designer window you will see your new entity data model. Have a look at the entities and their relationships.
5) Add a new item (our service) to the ASP.Net Web application project. Add a WCF Data Service.Give it a meaningful name.I have named it WCFDataService.svc.
6) Now I need to configure my WCF Data Service.I need to specify the class that contains my entities. In my case this is “AdventureWorksLTEntities“.We also need to specify some access rules that the client applications will have on the entities through the service. We want all our entities to be visible and readable from all clients.
The source code for the WCFDataService.svc.cs file follows.
namespace HostWCFDataService
{
public class WCFDataService : DataService<<strong>AdventureWorksLTEntities</strong>>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
// Examples:
// config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
<strong> config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);</strong>
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
}
7) View your web service in the browser. In my case it is (http://localhost:1741/WCFDataService.svc/) and I can view all the entities.
Because according to REST all resources have a URI we can get only the data for the Customers entity.We can do that by passing to the service this URI.
http://localhost:1741/WCFDataService.svc/Customers
The WCF Data Service will return XML data which contains information about all the customers in the entity. This is plain old XML.
In a similar fashion you can get data for only a customer. The service will send back the correct information in XML format as long as we pass it (through GET) a valid URI.
In this case I will pass it http://localhost:1741/WCFDataService.svc/Customers(1) , if I am interested in the first customer.Ηave a look at the picture below
I hope by now that it is quite evident to all what the similarities / differences of SOAP and REST.
8) Now we need to create our simple WPF application and call the WCF Data service.We need to build our UI first.We will add a ListBox control. The value of the CompanyName field for each record in the Customer table of the database (CompanyName property of the Customer entity in our EDM) will appear in the ListBox control. When the user selects a value the FirstName and LastName values will also appear for that record in a simple TextBlock control.
The whole code for the MainWindow.xaml follows.
<Window x:Class="WpfWcfDataServiceApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Customers" Height="500" Width="500" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded"> <Grid> <StackPanel> <ListBox Name="customersListBox" Height="400" Margin="10" BorderBrush="Black" DisplayMemberPath="CompanyName" SelectionChanged= "customersListBox_SelectionChanged" /> <TextBlock Name="customerTextBlock" Margin="10" Background="#FFBAABC1" FontFamily="Arial" FontSize="14" /> </StackPanel> </Grid> </Window>
9) Now we need to add a Service reference to our client application. Click Add Service Reference and then hit Discover button (in the new window that will pop up).You will see the service. Give the namespace a meaningful name (e.g AdventureWorksDataService). Visual studio will add the necessary references and generate all the necessary proxy classes that will help us talk to the service.Have a look at the Reference.cs file that is inside the Service References folder.You must have a good look at the DataServiceContext class which represents runtime context of data service.After you add a service reference, in this class there is a property for each entity (e.g ctx.Products).Our AdventureWorksLTEntities class inherits from DataServiceContext class.This class is also responsible for tracking entities. Another class you should look into is DataServiceQuery class which represents a request to the service. This class implements the IQueryable interface and that is why we wan write LINQ queries (you will see that later on) to talk to the service.Ιt also returns IEnumerable of the requested entity type.Αll queries are instances of the DataQueryService class and all queries belong to a data service context.Those queries are translated into HTTP GET requests and when a response comes back this response is translated into instances of the entity classes. Another very important class is the DataServiceCollection class that represents a dynamic collection of entity objects. This class inherits from the ObservableCollection(T) and also implements INotifyPropertyChanged and INotifyCollectionChanged interfaces.
10) Now it is time to write some code in the code behind files to handle the Window_Loaded and the customersListBox_SelectionChanged events.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private AdventureWorksLTEntities ctx = null;
private Customer customer = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ctx = new AdventureWorksLTEntities(new Uri("http://localhost:1741/WCFDataService.svc/"));
var customersQuery =from cust in ctx.Customers select cust;
customersListBox.ItemsSource = customersQuery.ToList();
}
private void customersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
customer = (Customer)customersListBox.SelectedItem;
customerTextBlock.Text = string.Format("The customer's firstname is {0} and his lastname is {1}",
customer.FirstName, customer.LastName);
}
}
The code is very easy to follow. I am just using standard LINQ queries.
11) Run your application and select a customer (CompanyName). You will get more information for this customer in the TextBlock Control.
Have a look at the picture below to see what happens when I run my application
12) Obviously we could loop through our customers and rewrite our code. We could write our code in the Window_Loaded event handling routine in a different way. Have a look at the code below.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private AdventureWorksLTEntities ctx = null;
private Customer customer = null;
private List<Customer> customersList = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ctx = new AdventureWorksLTEntities(new Uri(
"http://localhost:1741/WCFDataService.svc/"));
//var customersQuery =
// from cust in ctx.Customers
// select cust;
//customersListBox.ItemsSource = customersQuery.ToList();
customersList = new List<Customer>();
foreach (Customer cust in ctx.Customers)
{
customersList.Add(cust);
}
customersListBox.ItemsSource = customersList;
}
private void customersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
customer = (Customer)customersListBox.SelectedItem;
customerTextBlock.Text = string.Format(
"The customer's firstname is {0} and his lastname is {1}",
customer.FirstName, customer.LastName);
}
}
13) I will create another window. In this window I will get the information for a specific customer. I will have a textbox control in the UI and the user will insert the Customer ID and hit the Find button. Then the information for that customer will be displayed in the textbox controls that are also part of the UI. Add another item in your WPF application, a WPF window. Name it GetCustomer.xaml. In order to launch this window from the MainWindow.xaml we need to modify the XAML in this window and add a button.The XAML for the MainWindow.xaml is
<Grid> <StackPanel> <ListBox Name="customersListBox" Height="400" Margin="10" BorderBrush="Black" DisplayMemberPath="CompanyName" SelectionChanged= "customersListBox_SelectionChanged" /> <TextBlock Name="customerTextBlock" Margin="10" Background="#FFBAABC1" FontFamily="Arial" FontSize="14" /> <Button Name="btnGetCustomer" Background="Brown" BorderBrush="Azure" Content="GetCustomerData" FontWeight="Bold" FontFamily="Batang" FontSize="14" Width="200" Height="100" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnGetCustomer_Click"></Button> </StackPanel> </Grid>
We need to add some code in the button click event handling routine.We need to change the MainWindow.xaml.cs code.
private void btnGetCustomer_Click(object sender, RoutedEventArgs e)
{
var getcustomer = new GetCustomer();
getcustomer.Show();
}
So when the user clicks the button the new window pops up.
14) Now we need to build the UI for the GetCustomer window according to the requirements outlined in the previous paragraphs.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox Name="findTextBox" Margin="15,3,3,3"
Width="50" Height="25" />
<Button Name="findButton"
Content="Find"
Margin="10,5,5,5" Width="50" Height="25"
Click="findButton_Click"/>
</StackPanel>
<Grid Name="customerGrid"
Grid.Row="1" Margin="5,0,0,0"
Width="450" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="Company Name"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=CompanyName}"
Grid.Row="0" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="First Name"
Grid.Row="1" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=FirstName}"
Grid.Row="1" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Middle Name"
Grid.Row="2" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=MiddleName}"
Grid.Row="2" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Last Name"
Grid.Row="3" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=LastName}"
Grid.Row="3" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Title" Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Title}"
Grid.Row="4" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Sales Person"
Grid.Row="5" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=SalesPerson}"
Grid.Row="5" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Email Address"
Grid.Row="6" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=EmailAddress}"
Grid.Row="6" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Phone"
Grid.Row="7" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Phone}"
Grid.Row="7" Grid.Column="1"
Margin="3" Height="25" />
</Grid>
</Grid>
We add the TextBox controls and the TextBlock controls. Those TextBox controls have their Text property bound to the value that will return the WCF Data Service and basically are the properties of the Customer entity. We also have the TextBox control that the user will enter the Customer ID and hit the Find button.This is the code for the GetCustomer.xaml.cs file.
public partial class GetCustomer : Window
{
public GetCustomer()
{
InitializeComponent();
}
private AdventureWorksLTEntities ctx = null;
private Customer customer = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ctx = new AdventureWorksLTEntities(new Uri(
"http://localhost:1741/WCFDataService.svc/"));
}
private void findButton_Click(object sender, RoutedEventArgs e)
{
try
{
int FindID=Convert.ToInt32(findTextBox.Text);
customer =
(from cust in ctx.Customers
where (cust.CustomerID == FindID)
select cust).Single();
customerGrid.DataContext = customer;
}
catch (Exception ex)
{
customerGrid.DataContext = null;
}
}
}
I am using a simple LINQ query and set the Grid’s DataContext property to the customer entity that the WCF Service returns as XML raw data and the WCF Data Services Client library converts the XML data to a .Net entity.
15) Run your application and hit the button in the MainWindow window.In the new window type “4″ in the textbox control and hit the Find button.
Have a look at the picture below to see what happens when I run the application. I am sure that if you followed all the steps so far you will have similar results.
16) Moving on I would like to show you how to find related data in the database through our middle tier, thus the WCF Data service.In this example we will load some information from the Customer (table/entity) and then display the related data in the SalesOrderHeader (table/entity).I will create another window. In this window I will have various controls. I will have a ListBox control where the CompanyName values will appear for the customers.When the user clicks a customer from the top ListBox control in the second ListBox control just below it the orders will appear and in the tetboxes some more field with values for this particular order .
Add another item in your WPF application, a WPF window. Name it GetCustomerOders.xaml. In order to launch this window from the MainWindow.xaml we need to modify the XAML in this window and add a button.The XAML for the MainWindow.xaml becomes
<Grid> <StackPanel> <ListBox Name="customersListBox" Height="400" Margin="10" BorderBrush="Black" DisplayMemberPath="CompanyName" SelectionChanged= "customersListBox_SelectionChanged" /> <TextBlock Name="customerTextBlock" Margin="10" Background="#FFBAABC1" FontFamily="Arial" FontSize="14" /> <Button Name="btnGetCustomer" Background="Brown" BorderBrush="Azure" Content="GetCustomerData" FontWeight="Bold" FontFamily="Batang" FontSize="14" Width="200" Height="100" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnGetCustomer_Click"></Button> <Button Name="btnGetCustomerOrders" Background="DimGray" BorderBrush="Blue" Content="GetCustomerOrdersData" FontWeight="Bold" FontFamily="Batang" FontSize="14" Width="200" Height="100" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnGetCustomerOrders_Click"></Button> </StackPanel> </Grid>
We need to add some code in the button click event handling routine.We need to change the MainWindow.xaml.cs code.
private void btnGetCustomerOrders_Click(object sender, RoutedEventArgs e)
{
var getcustomerorders = new GetCustomerOders();
getcustomerorders.Show();
}
17) Now we need to add the XAML code for the GetCustomerOders.xaml. We need to have a functional UI before we move on writing our code
<Window.Resources>
<DataTemplate x:Key="CustomerTemplate">
<StackPanel Margin="0,0,0,5"
Orientation="Horizontal">
<TextBlock Margin="10,0,0,0"
VerticalAlignment="Center"
Text="{Binding Path=CompanyName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="OrderTemplate">
<StackPanel Margin="0,0,0,5"
Orientation="Horizontal">
<TextBlock Margin="10,0,0,0"
VerticalAlignment="Center"
Text="{Binding Path=OrderDate}" />
<TextBlock Text=" (" />
<TextBlock VerticalAlignment="Center"
Text="{Binding Path=SalesOrderID}" />
<TextBlock Text=")" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="5*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Name="customersListBox" Grid.Row="0"
ItemTemplate="{StaticResource CustomerTemplate}"
SelectionChanged=
"customersListBox_SelectionChanged"
Margin="10"
BorderBrush="Black" />
<ListBox Name="ordersListBox" Grid.Row="1"
ItemTemplate="{StaticResource OrderTemplate}"
SelectionChanged=
"ordersListBox_SelectionChanged"
Margin="10"
BorderBrush="Black" />
<Grid Name="OrdersGrid" Grid.Row="2" Margin="5,0,0,0"
Width="600" HorizontalAlignment="Left" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="125" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="125" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="Due Date"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=DueDate}"
Grid.Row="0" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Ship Date"
Grid.Row="1" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=ShipDate}"
Grid.Row="1" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Modified Date"
Grid.Row="2" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=ModifiedDate}"
Grid.Row="2" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="Status"
Grid.Row="0" Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Status}"
Grid.Row="0" Grid.Column="3"
Margin="3" Height="25" />
<TextBlock Text="Sub Total"
Grid.Row="1" Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=SubTotal}"
Grid.Row="1" Grid.Column="3"
Margin="3" Height="25" />
<TextBlock Text="Comment"
Grid.Row="2" Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Comment}"
Grid.Row="2" Grid.Column="3"
Margin="3" Height="25" />
</Grid>
</Grid>
</Window>
Now I have my UI in Xaml and I must implement the event handling routines in the code behind. I handle the Window_Loaded event where I load the CompanyName value for every record in the Customers table. Then I handle the customersListBox_SelectionChanged event where I load in the ordersListBox the OrderDate and the SalesOrderID for the selected customer.Finally when the value in the ordersListBox is selected more information about this order is displayed in the TextBox controls.
This is the code for the GetCustomerOders.xaml.cs file
public partial class GetCustomerOders : Window
{
public GetCustomerOders()
{
InitializeComponent();
}
private AdventureWorksLTEntities ctx = null;
private Customer customer = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ctx = new AdventureWorksLTEntities(new Uri("http://localhost:1741/WCFDataService.svc/"));
var customersQuery =from cust in ctx.Customers
select cust;
customersListBox.ItemsSource = customersQuery.ToList();
}
private void customersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
customer = (Customer)customersListBox.SelectedItem;
ctx.LoadProperty(customer, "SalesOrderHeaders");
foreach (var order in customer.SalesOrderHeaders)
{
ctx.LoadProperty(order, "OrderDate");
}
ordersListBox.ItemsSource = customer.SalesOrderHeaders;
}
private void ordersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
OrdersGrid.DataContext =(SalesOrderHeader)ordersListBox.SelectedItem;
}
}
Have a look at the picture below to see what I mean. Run your application and see the results for yourself. You should have similar results.
Leave a comment if you want the source code.
Hope it helps!!!
Using WCF services in WPF applications January 17, 2012
Posted by fofo in C#, Visual Studio 2008, Visual Studio 2010, VS 2010, WCF Service, WPF, XAML.1 comment so far
In this post I will provide you with hands-on examples on how to retrieve data from a WCF service and bind the data to a WPF data bindable control that resides inside a WPF window. This is not going to be a post that will look into WCF Services in great detail. In the near future I will be writing posts on WCF.In a nutshell WCF provides a unified programming model for building service oriented applications. You write your service once and you can expose it (through endpoints) to multiple protocols without having to rewrite the service.The service is written in a .Net language and consists of operations that are exposed so clients can execute them.When you host the service you make it available to clients by providing one or more endpoints. Bindings are used to determine how a service endpoint will communicate with a client endpoint.
Obviously we can use other ways to talk to data sources. We can use ADO.Net, datasets, LinqToSQL, Entity Framework,Web services,WCF data services and custom data objects to fetch data from a data source and bind it our WPF controls.
Let’s move on with our hands-on examples.Ι will provide several examples. In the first one I will use a custom data object. In the second one I will use a database.
I assume that you have access to a version of SQL Server and AdventureWorkLT database.
If you do not, you can download and install the free SQL Server Express edition from here. If you need the installation scripts for the sample AdventureWorksLT database, click here . We will use our WCF service to get data from the the Customers table of the AdventureWorksLT database.
1) Launch Visual Studio. I will be using Visual Studio 2010 Ultimate edition. I will be using C# as the development language.
2) Add a WPF application to your solution. Give it a meaningful name. Add a WCF Service application to your solution.Give it a meaningful name.Visual Studio will create the necessary files.Rename the service from Service1 (IService1) to FootballerService (IFootballerService).
3) Now we are ready to write some code in the IFootballerService.cs file.We need to define the method will get the customers from the database table.
[ServiceContract]
public interface IFootballerService
{
[OperationContract]
List<Footballer> GetFootballers();
// TODO: Add your service operations here
}
4) I will also need to create a DataContract.Since I pass instances of the Footballer object I need to do that.
This is the code.
[DataContract]
public class Footballer
{
[DataMember]
public int FootballerID { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public string Position { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string PlaysFor { get; set; }
public Footballer( int id,string name,string surname,string position,int age,string playsfor)
{
this.FootballerID = id;
this.FirstName = name;
this.LastName = surname;
this.Position = position;
this.Age = age;
this.PlaysFor = playsfor;
}
}
I am decorating the Footballer class as DataContract.We need to do that so .Net WCF serialiser can take those .Net objects and serialise them to XML so they can passed back to the clients.It knows how to do that with simple types but not with more complex ones. So that is why we must tell it.Do not forget that we still exchange XML SOAP messages over HTTP(or TCP).
5) Now we are ready to implement the Interface.We open the FootballerService.svc.cs file and we write the following code.
public class FootballerService : IFootballerService
{
public List<Footballer> GetFootballers()
{
var footballers = new List<Footballer>();
footballers.Add(new Footballer(1, "Steven", "Gerrard", "Attacking Midfielder" ,31 ,"Liverpool"));
footballers.Add(new Footballer(2, "Lionel", "Messi", "Striker",24,"Barcelona"));
footballers.Add(new Footballer(3, "Ryan", "Giggs", "Winger", 38, "Man United"));
return footballers;
}
}
6) Test your service. The host ( the service must be hosted somewhere ) in our example is the ASP.Net development server.
7) Now let’s call the service from the client. The first thing to do is to add a service reference to the WPF application (client project).
Click Add Service Reference and then hit Discover button (in the new window that will pop up).You will see the service. Give the namespace a meaningful name (CustomersServices).Click Advanced and then in the Data type – Collection type, select the System.Collections.ObjectModel.ObservableCollection and click OK.Visual Studio will generate all the necessary proxy classes.
8) Let’s add some xaml code on the WPF window.I will use a ListBox and TextBlock control.
<Grid> <StackPanel> <ListBox Name="FootballerBox" Height="300" Margin="28" BorderBrush="Cyan" DisplayMemberPath="FirstName" SelectionChanged="FootballerBox_SelectionChanged" /> <TextBlock Name="FootballerText" Margin="20,2,2,2"></TextBlock> </StackPanel> </Grid>
9) Now we need to add some simple code in the code behind file and for the Window_Loaded events and FootballerBox_SelectionChanged event handling routines.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private FootballerServices.FootballerServiceClient footballersService = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
footballersService = new FootballerServices.FootballerServiceClient();
try
{
FootballerBox.ItemsSource = footballersService.GetFootballers();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void FootballerBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var footballer = (FootballerServices.Footballer)FootballerBox.SelectedItem;
FootballerText.Text = String.Format("His surname is {0}. His age is {1} and the position he plays is {2}.He plays for {3}", footballer.LastName,footballer.Age,footballer.Position,footballer.PlaysFor);
}
}
10) Run your application. You will see the ListBox control populated from the data the WCF service sends to it.When you select a name from the listbox you will see more details for the footballer on the textblock control.
11) Now we will move to the second example.In this example we will get data from the AdventureWorksLT database. Close your solution and create a new WPF application.Give it an appropriate name.
12) Let me explain what I want to do in the example. I will have my main WPF window (MainWindow.xaml). I will place a button on it.Then I will create another WPF window and I will name it GetCustomers (Getcutomers.xaml).In this window I will have a ListBox control and various textblock and textbox controls. In the ListBox control I will only get the CompanyName of the customer.When the user selects the CompanyName in the ListBox control more information will appear in the TextBox controls.This is our client application.Let’s have a look in the markup for the MainWindow.xaml window.
<Grid> <StackPanel> <Button Content="Get a list of customers" Name="listOfCustomersButton" MaxWidth="200" MinHeight="35" Margin="5,25,5,5" Click="listOfCustomersButton_Click"/> </StackPanel> </Grid>
Add another window in the WPF application.Name it GetCustomers (GetCustomers.xaml). Now let’s have a look at the code behind for the MainWindow.xaml.cs.
private void listOfCustomersButton_Click(object sender, RoutedEventArgs e)
{
var getCustomers = new GetCustomers();
getCustomers.Show();
}
13)We need to create a service that will get the data from the underlying database. Create a WCF Service Application and give it an appropriate name. Now you have two projects in your solution.Name the service AdventureWorksService (IAdventureWorksService.cs). Now we need to define the service contract, the public methods that can be accessible from the client and finally the DataContracts.The code follows.
[ServiceContract]
public interface IAdventureWorksService
{
[OperationContract]
List<CustomerSummary> GetCustomers();
[OperationContract]
Customer GetCustomer(int customerID);
}
[DataContract]
public class CustomerSummary
{
[DataMember]
public int CustomerId { get; set; }
[DataMember]
public string CompanyName { get; set; }
//[DataMember]
//public string City { get; set; }
//[DataMember]
//public string Country { get; set; }
}
[DataContract]
public class Customer
{
[DataMember]
public int CustomerId { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string MiddleName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public string CompanyName { get; set; }
[DataMember]
public string SalesPerson { get; set; }
[DataMember]
public string EmailAddress { get; set; }
[DataMember]
public string Phone { get; set; }
}
I am going to have two methods.The first one GetCustomers (which will be implemented later on and used to bind the company name to the ListBox control) will return the CustomerID and CompanyName fields from the database.The second method GetCustomer will return more information about the Customer when we pass it the CustomerID as an input parameter.The fields we are interested in are CustomerID,Title,FirstName,MiddleName,LastName,CompanyName,SalesPerson,EmailAddress,Phone
This is the method that will populate the variousTextbox controls in the GetCustomers window when the user selects the Company Name from the ListBox control.
That is why need to define two classes Customer and CustomerSummary.
14) Now we need to implement the methods in the AdventureWorksService.svc.cs file.The code follows.
public class AdventureWorksService : IAdventureWorksService
{
private CustomerSummary customerSummary = null;
private List<CustomerSummary> customers = null;
private Customer customer = null;
string connectionString = ConfigurationManager.ConnectionStrings["AdventureWorksLTConnectionString"].ConnectionString;
public List<CustomerSummary> GetCustomers()
{
customers = new List<CustomerSummary>();
using (var cnn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(
"SELECT TOP 5 CustomerID, CompanyName " +
"FROM SalesLT.Customer ORDER BY CustomerID", cnn))
{
cnn.Open();
using (SqlDataReader CustomersReader =
cmd.ExecuteReader())
{
while (CustomersReader.Read())
{
customerSummary = new CustomerSummary();
customerSummary.CustomerId =
CustomersReader.GetInt32(0);
customerSummary.CompanyName =
CustomersReader.GetString(1);
customers.Add(customerSummary);
}
}
}
}
return customers;
}
public Customer GetCustomer(int customerID)
{
customer = new Customer();
using (var cnn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(
"SELECT CustomerID,Title,FirstName,MiddleName,LastName,CompanyName,SalesPerson,EmailAddress,Phone FROM SalesLT.Customer " +
"WHERE CustomerID = @customerId", cnn))
{
cmd.Parameters.Add(new SqlParameter(
"@customerId", customerID));
cnn.Open();
using (SqlDataReader CustomersReader =
cmd.ExecuteReader())
{
while (CustomersReader.Read())
{
customer.CustomerId =
CustomersReader.GetInt32(0);
if (CustomersReader.IsDBNull(1) == true)
{
customer.Title = string.Empty;
}
else
{
customer.Title =
CustomersReader.GetString(1);
}
customer.FirstName =
CustomersReader.GetString(2);
if (CustomersReader.IsDBNull(3) == true)
{
customer.MiddleName = string.Empty;
}
else
{
customer.MiddleName =
CustomersReader.GetString(3);
}
customer.LastName =
CustomersReader.GetString(4);
if (CustomersReader.IsDBNull(5) == true)
{
customer.CompanyName = string.Empty;
}
else
{
customer.CompanyName =
CustomersReader.GetString(5);
}
if (CustomersReader.IsDBNull(6) == true)
{
customer.SalesPerson = string.Empty;
}
else
{
customer.SalesPerson =
CustomersReader.GetString(6);
}
if (CustomersReader.IsDBNull(7) == true)
{
customer.EmailAddress = string.Empty;
}
else
{
customer.EmailAddress =
CustomersReader.GetString(7);
}
if (CustomersReader.IsDBNull(8) == true)
{
customer.Phone = string.Empty;
}
else
{
customer.Phone =
CustomersReader.GetString(8);
}
}
}
}
}
return customer;
}
}
Let me explain what I am doing here.I am getting the connection string
string connectionString = ConfigurationManager.ConnectionStrings["AdventureWorksLTConnectionString"].ConnectionString;
In the web.config you need to add those lines of code.
<connectionStrings> <add name="AdventureWorksLTConnectionString" connectionString="Data Source=.;Initial Catalog=AdventureWorksLT;Integrated Security=True" /> </connectionStrings>
For the GetCustomers method I create a new connection object and open the connection. I create a new SQLCommand object that holds the query and I execute the query. I loop through the results of the query and get the CustomerID and CompanyName values for each customer.
For the GetCustomer method, I create a new connection object and open the connection. I create a new SQLCommand object that holds the query and I execute the query.In this query I need to pass the parameter as well and I do that.Then I loop through the results.As you see I also take into account if the field has the NULL value.
Finally I return a customer object that holds the values of CustomerID,Title,FirstName,MiddleName,LastName,CompanyName,SalesPerson,EmailAddress,Phone for the particular CustomerID value I pass as the input parameter.
15) Now we need to add the markup for the GetCustomers.xaml page.The markup follows. You need to paste it in your own window and it will make sense.In order for you to understand what is going on it will be handy if you know a few things of how data binding works in WPF.
<Window.Resources>
<DataTemplate x:Key="CustomerTemplate">
<StackPanel Margin="0,0,0,5"
Orientation="Horizontal">
<TextBlock Margin="10,0,0,0"
VerticalAlignment="Center"
Text="{Binding Path=CompanyName}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Name="customersListBox"
Grid.Row="0" Margin="10"
BorderBrush="Black"
ItemTemplate="{StaticResource CustomerTemplate}"
SelectionChanged="customersListBox_SelectionChanged"/>
<Grid Name="customerGrid" Grid.Row="1" Margin="5,0,0,0" Width="450" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="Title"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Title}"
Grid.Row="0" Grid.Column="1"
Margin="3" Height="25" />
<TextBlock Text="First Name" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=FirstName}" Grid.Row="1" Grid.Column="1" Margin="3" Height="25" />
<TextBlock Text="Middle Name" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=MiddleName}"
Grid.Row="2" Grid.Column="1" Margin="3" Height="25" />
<TextBlock Text="Last Name" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=LastName}" Grid.Row="3" Grid.Column="1"Margin="3" Height="25" />
<TextBlock Text="Company Name" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=CompanyName}" Grid.Row="4" Grid.Column="1" Margin="3" Height="25" />
<TextBlock Text="Sales Person" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=SalesPerson}" Grid.Row="5" Grid.Column="1" Margin="3" Height="25" />
<TextBlock Text="Email" Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=EmailAddress}" Grid.Row="6" Grid.Column="1" Margin="3" Height="25" />
<TextBlock Text="Phone" Grid.Row="7" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" />
<TextBox Text="{Binding Path=Phone}" Grid.Row="7" Grid.Column="1" Margin="3" Height="25" />
HorizontalAlignment="Left" Margin="10,0,0,0" />
</Grid>
</Grid>
</Window>
16) we need to add a service referenceto the WPF application (client project).
Click Add Service Reference and then hit Discover button (in the new window that will pop up).You will see the service. Give the namespace a meaningful name (WCFAdventureWorksServices).Click Advanced and then in the Data type – Collection type, select the System.Collections.ObjectModel.ObservableCollection and click OK.Visual Studio will generate all the necessary proxy classes.
17) The code behind for the GetCustomers.xaml.cs file follows.The code is extremely easy to follow. I use the Window_Loaded event to bind data to the ListBox control.I do that by setting the ItemSource property of the ListBox (CustomersListBox) control to the GetCustomers method of the service.When the user selects a value from the ListBox the Selection_Changed event is fired and I set the DataContext property of the Grid to the values of the GetCustomer method.
private WCFAdventureWorksServices.AdventureWorksServiceClient
advService = null;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
advService = new
WCFAdventureWorksServices.AdventureWorksServiceClient();
try
{
customersListBox.ItemsSource =
advService.GetCustomers();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void customersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int customerID =
((WCFAdventureWorksServices.CustomerSummary)
((ListBox)sender).SelectedItem).CustomerId;
try
{
customerGrid.DataContext = advService.GetCustomer(customerID);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
17) Run your application and make sure that everything works as expected. Click on the Company Names values in the ListBox control and see the details for each customer appearing in the TextBox controls.
Leave a comment if you need the source code.
Hope it helps!!!!
Windows forms and WPF Interoperability January 9, 2012
Posted by fofo in WPF, XAML, Visual Studio 2010.Tags: Interoperability;Windows Forms;
1 comment so far
In this post I will not be investigating at what some people call the “Windows single technology applications” which basically means that we build WinForms apps for the windows operating systems using only Windows Forms controls or alternatively build a windows WPF application using only the built-in or 3rd party WPF controls.
I will be looking into the “Mixed technology applications”. In other words how to build Windows Forms applications using both Windows Forms and WPF controls.Moreover how to build WPF applications using both WPF and Windows Forms controls.I will be using C# to build those applications.
I know that many people since the introduction of WPF have designed and implemented using this awesome new technology introduced with .NET 3.0.
But what about our existing WinForms applications? Are we going to rewrite everything?What about the controls we built for a WinForms application? Are we going to rewrite those too? What about 3rd party controls we have purchased? We do not want to spend time and money to write functionality that we already have got.
In a nutshell we want to have interoperability and that it is possible with the current technologies.It is possible to reuse than recreate.
Let’s start with our first example. In this example I will show how to add an existing Windows Form to a WPF application.
1) Launch Visual Studio. I will be using Visual Studio 2010 Ultimate edition.
2) Create a new WPF application and give it a name of your choice. Choose C# as the development language.
3) Add a new item to your application, a new Window(WPF). Name it Footballers.xaml
4) Add the following xaml code to the MainWindow.xaml file
<StackPanel> <Button Content="Log in" Margin="5,25,5,5" MaxWidth="200" MinHeight="35" Name="loginButton" Click="loginButton_Click"/> <Button Content="Footballers window" Margin="5,25,5,5" MaxWidth="200" MinHeight="35" Name="footballersWindowButton" Click="footballersWindowButton_Click"/> <Button Content="Footballers form" Margin="5,25,5,5" MaxWidth="200" MinHeight="35" Name="footballersFormButton" Click="footballersFormButton_Click"/> <Button Content="About" Margin="5,25,5,5" MaxWidth="200" MinHeight="35" Name="aboutButton" Click="aboutButton_Click"/> </StackPanel>
5) Run your application so you can have a feeling on what we are going to build.
6) As you see we have a button that when clicked must launch the Footballers window.This is the code to achieve that.
private void footballersWindowButton_Click(object sender, RoutedEventArgs e)
{
var fooballers = new Footballers();
fooballers.Show();
}
7) We have also added an “About” button. That will launch an About form. We know that Windows Forms have such functionality and we will utilise it. Add a new item to your application, an About Box (Add –> New Item –>Windows Forms –>About Box).Name it AboutForm.References are added automatically to the application and the Windows Forms designer pops up showing the “AboutForm” form.
8) When you select the AboutForm (Windows Form) you will see in the Toolbox area the Windows Forms controls.When you select the .xaml file in the Toolbox the WPF controls will appear.
9) I need to add login functionality to my application. I will use an existing Windows Forms (Login Form) that I have already created. I will add an existing item (a LoginForm.cs) file to my application.
10) In the MainWindow.xaml we will add the the code required to launch the Login form and the About form.The code follows.
private void loginButton_Click(object sender, RoutedEventArgs e)
{
var login = new LoginForm();
login.Show();
}
private void aboutButton_Click(object sender, RoutedEventArgs e)
{
var about = new AboutForm();
about.Show();
}
11) Run your application and click the relevant buttons to launch the windows.
12) As you see it is pretty easy to add Window Forms to a WPF application. Maybe they use a different graphical subsystem to render but it is very easy to launch window forms from a WPF application. Now I would like to show you how easy it is to share information between the various forms of the application. I want to store the login name in a variable and show it in the MainWindow. Add a class file to your application. Name it General.cs. This is the code for the static class. Basically we define a string (LoginName).
public static class General
{
public static string LoginName = string.Empty;
}
13) Now we will add some code in the LoginForm.cs that will store the username the user enters in the form.This is the code
private void OK_Click(object sender, EventArgs e)
{
General.LoginName = UsernameTextBox.Text;
this.Close();
}
14) The next step is to change the code in the MainWindow.xaml.cs so that when the
private void loginButton_Click(object sender, RoutedEventArgs e)
{
var login = new LoginForm();
if (login.ShowDialog() == System.Windows.Forms.DialogResult.OK)
MessageBox.Show("Welcome " + General.LoginName);
}
15) Run your application and click the Log in button. Add a new username and a password and click “OK”. You will see the Message box popping up with the name you entered in the login form.With this simple example you see how easy it is to share information among the two forms that are part of different window technologies.
16) Now let’s add some functionality to the button”Footballers Window”.
We will get data from a database and display it in the Footballers.xaml window. But we will need a database first. So in my case I have created a small database with a single table.
This is the T-SQL code you need to execute so you can have the same data.
USE [master]
GO
/****** Object: Database [football] Script Date: 01/07/2012 15:22:13 ******/
CREATE DATABASE [football] ON PRIMARY
( NAME = N'football', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\football.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'football_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\football_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [football] SET COMPATIBILITY_LEVEL = 100
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [football].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [football] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [football] SET ANSI_NULLS OFF
GO
ALTER DATABASE [football] SET ANSI_PADDING OFF
GO
ALTER DATABASE [football] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [football] SET ARITHABORT OFF
GO
ALTER DATABASE [football] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [football] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [football] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [football] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [football] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [football] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [football] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [football] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [football] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [football] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [football] SET DISABLE_BROKER
GO
ALTER DATABASE [football] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [football] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [football] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [football] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [football] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [football] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [football] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [football] SET READ_WRITE
GO
ALTER DATABASE [football] SET RECOVERY FULL
GO
ALTER DATABASE [football] SET MULTI_USER
GO
ALTER DATABASE [football] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [football] SET DB_CHAINING OFF
GO
USE [football]
GO
/****** Object: Table [dbo].[footballers] Script Date: 01/07/2012 15:21:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[footballers](
[id] [int] IDENTITY(1,1) NOT NULL,
[firstname] [varchar](50) NOT NULL,
[lastname] [varchar](50) NOT NULL,
[isActive] [bit] NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[footballers] ON
INSERT [dbo].[footballers] ([id], [firstname], [lastname], [isActive]) VALUES (1, N'Robbie', N'Fowler', 1)
INSERT [dbo].[footballers] ([id], [firstname], [lastname], [isActive]) VALUES (2, N'Steven', N'Gerrard', 1)
INSERT [dbo].[footballers] ([id], [firstname], [lastname], [isActive]) VALUES (3, N'Kenny', N'Dalglish', 0)
SET IDENTITY_INSERT [dbo].[footballers] OFF
}
Connect to the local instance of SQL Server and in a new query window execute the T-SQL code provided above.
17) In the Visual Studio go to Data–>Add New Data Source…Add a new data source.In the wizard select Database and click Next. Then select Dataset and click Next.In the next step create a new connection that points to the football database.Press OK. In the wizard click Next and Next again.In the database objects window choose footballers table and finally Finish.Drag and drop the Data Sources window on the Footballers window.Please have a look at the generated code in the Footballers.xaml and Footballers.xaml.cs files.
In my case the code in the Footballers.xaml.cs is the following.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowsFormToWPF.footballDataSet footballDataSet = ((WindowsFormToWPF.footballDataSet)(this.FindResource("footballDataSet")));
// Load data into the table footballers. You can modify this code as needed.
WindowsFormToWPF.footballDataSetTableAdapters.footballersTableAdapter
footballDataSetfootballersTableAdapter = new WindowsFormToWPF.footballDataSetTableAdapters.footballersTableAdapter();
footballDataSetfootballersTableAdapter.Fill(footballDataSet.footballers);
System.Windows.Data.CollectionViewSource footballersViewSource =
((System.Windows.Data.CollectionViewSource)(this.FindResource("footballersViewSource")));
footballersViewSource.View.MoveCurrentToFirst();
}
The code for the Footballers.xaml follows
<Window.Resources>
<my:footballDataSet x:Key="footballDataSet" />
<CollectionViewSource x:Key="footballersViewSource"
Source="{Binding Path=footballers, Source={StaticResource footballDataSet}}" />
</Window.Resources>
<Grid DataContext="{StaticResource footballersViewSource}">
<DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" Height="134"
HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="12,21,0,0" Name="footballersDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="222">
<DataGrid.Columns>
<DataGridTextColumn x:Name="idColumn" Binding="{Binding Path=id}" Header="id" IsReadOnly="True" Width="SizeToHeader" />
<DataGridTextColumn x:Name="firstnameColumn" Binding="{Binding Path=firstname}" Header="firstname" Width="SizeToHeader" />
<DataGridTextColumn x:Name="lastnameColumn" Binding="{Binding Path=lastname}" Header="lastname" Width="SizeToHeader" />
<DataGridCheckBoxColumn x:Name="isActiveColumn" Binding="{Binding Path=isActive}" Header="is Active" Width="SizeToHeader" />
</DataGrid.Columns>
</DataGrid>
</Grid>
18) Run your application and click on the “Footballers window” button to see the new window populated with data from the dataset.
19) Now we need to add some functionality to the fourth button “Footballers form”. Add another form (Windows Form) to your application.Name it FootballersForm.cs
Bring the form on the designer.From the Data Sources window, click Details from the drop-down and then drag and drop it on the FootballersForm window.Have a look at the code in the FootballersForm.cs file. Now we need to add some code to launch this Windows Form window from the MainWindow.xaml file.
This is the code for the footballersFormButton_Click event handling routine.
private void footballersFormButton_Click(object sender, RoutedEventArgs e)
{
var FootballersForm = new FootballersForm();
FootballersForm.Show();
}
20) Run your application and click on all buttons to see all the windows popping up. You can see how we can incorporate Window Forms in a WPF project.
21) At this point I would like to mention something that every developer who will try “Interop” should know. Launch Spy++ and move it over a Windows form window. You will see so many handles available for almost any control on the form. You can check that yourself by launching Spy++ and trying to find the handle for the various controls of the Windows Forms windows. You will see that you will get only one handle for the WPF windows.
Have a look at the pictures below to see what I mean.
22) Another thing worth pointing out is how keyboard input is handled in a Windows form window that is part of a WPF application. Launch your application again. Click on the “Footballers form” window and in the window that pops up, try to use the tab key to move between the fields of the record. You will notice that you cannot do that.That is because the WPF application (host application) receives the keyboard input messages but does not know how to pass that keyboard input message to the Windows Form window. Let’s fix that. First we need to add a reference to the WindowsFormIntegration assembly.Now we will add some code to the App.xaml and App.xaml.cs files.
In the App.xaml file we add the Startup application event.Have a look at the code below.
<Application x:Class="WindowsFormToWPF.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" Startup="Application_Startup" >
We add the event handling routine for the event in the App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
WindowsFormsHost.EnableWindowsFormsInterop();
//not necessary when running on windows vista or 7. But needed when you run on windows XP
System.Windows.Forms.Application.EnableVisualStyles();
}
}
As you can see I use the WindowsFormsHost class that allows us to host a Windows Forms control on a WPF application.
23) Launch your application again. Click on the “Footballers form” window and in the window that pops up, try to use the tab key to move between the fields of the record. You will be successful this time.
24) Now we can see another example where you can add an existing WPF window to a Windows Forms application.We need to add some references and Visual studio open the WPF window in the XAML designer.We will use the ElementHost class that can be used to host a Windows Presentation Foundation (WPF) element inside a Windows Forms application.Close this project/application and create a new Windows Forms application.Now we need to add a new WPF window. We are going to use an existing one, the one we created in the previous application, Footballers.xaml. In order to add all the necessary references to the Windows Forms application, in the Xaml designer drag and drop a label control on the Footballers.xaml.When you do that all the necessary references are added.Some of them are (Accessibility,PresentationCore, PresentationFramework).Now remove the label control.Add a button on the Windows form (main windows form-Form1.cs).In the button1_click event handling routine type
private void button1_Click(object sender, EventArgs e)
{
var footballers = new Footballers();
footballers.Show();
}
25) Now run your application and click on the button. The WPF window will show just fine.Try to move up and down the records using the up and down arrows from the keyboard. That will not work for the same reasons I explained before. The Windows Form (main – host application) receives the input messages from the keyboard but does not know how to pass them on to the WPF window.Let’s fix that.We need to add a reference to our application. We need to add a reference to the WindowsFormsIntegration assembly.In the button1_click event handling routine we need to add another line of code. The complete code follows.
private void button1_Click(object sender, EventArgs e)
{
var footballers = new Footballers();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(footballers);
footballers.Show();
}
26) Now let’s run the application again. Click on the button and in the WPF window move up and down the records using the up and down arrows from the keyboard. You will be successful this time.
27) We can also add a Windows Forms built-in or user control to a WPF window and vice versa.I will demonstrate that with additional examples.
28) I will be showing your first how to add a Windows Forms control in a WPF window.In order to do that I will be using the WindowsFormsHost class in the System.Windows.Forms.Integration namespace.
29) Create a new WPF application and choose a suitable name for it. Choose C# as the development language. Add references to the System.Windows.Forms and WindowsFormIntegration assemblies.I will be adding in XAML the assembly reference for Window Forms and mscorlib assemblies.
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:sys="clr-namespace:System;assembly=mscorlib"
30) Now in the XAML I will be adding a MaskedTextBox control that does not exist in the WPF ecosystem.This is the code in the MainWindow.xaml
<WindowsFormsHost>
<wf:MaskedTextBox x:Name="maskedTextBox" Mask="(999)-0000000" ValidatingType="{x:Type sys:Int32}" ></wf:MaskedTextBox>
</WindowsFormsHost>
Run your application and you will see the masked textbox appearing with no problems at all.
31) Finally I am going to provide an example on how to use WPF controls in WinForms Apps.Obviously we need to add references to the needed assemblies.We are going to use the ElementHost control. Add a new folder in your application, a WPF user control.Name it FrameWorkControl.xaml.
32) Αdd a reference to the System.Xaml assembly.
33) The code for the FrameWorkControl.xaml follows. I am basically having a ListBox control with some TextBlock elements inside a stackpanel.
<Grid> <ListBox Margin="5" Grid.Row="1" Grid.Column="0" Name="DotNetListBox" SelectionChanged="DotNetListBox_SelectionChanged"> <StackPanel Margin="0,0,0,5" Orientation="Horizontal"> <Label Content="ASP.Net" Padding="10" Margin="10" FontFamily="Batang" FontSize="16"></Label> <TextBlock MaxWidth="500" Margin="10,0,0,0" TextWrapping="Wrap" Tag="ASP.Net" Text="ASP.NET is the next generation ASP, but it's not an upgraded version of ASP. ASP.NET is an entirely new technology for server-side scripting" Width="265" Height="66"></TextBlock> </StackPanel> <StackPanel Margin="0,0,0,5" Orientation="Horizontal"> <Label Content="WPF" Padding="10" Margin="10" FontFamily="Batang" FontSize="16"></Label> <TextBlock MaxWidth="500" Margin="10,0,0,0" TextWrapping="Wrap" Tag="WPF" Text="Windows Presentation Foundation, WPF, provides a unified framework for building applications and high-fidelity experiences in Windows that blend application UI, documents, and media content" Width="300" Height="94"></TextBlock> </StackPanel> </ListBox> </Grid>
34) For the DotNetListBox_SelectionChanged event handling routine type.
public string SelectedTechnology { get; set; }
private void DotNetListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TextBlock dotnetText = ((StackPanel)DotNetListBox.SelectedValue).Children.OfType<TextBlock>().First();
this.SelectedTechnology = dotnetText.Tag.ToString();
}
}
}
35) Drag and drop an ElementHost control.Click the smarttag icon and in the “Selected Hosted Content:” select the FrameWork control.Now our user control is inside (hosted) inside the Windows Forms application.Resize appropriately.
36) Now add a button in the main form. In the click event handling routine type
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(string.Format( "You selected {0}",((FrameWorkControl)elementHost1.Child).SelectedTechnology));
}
Run your application. Select you favourite technology and click the button. Your favourite technology will pop up.
I understand that this is a very long post but hopefully you will find it very interesting.
Leave a comment with your email if you need the source code.
Hope it helps!!!!
Using WCF Services in Silverlight 4.0 applications November 21, 2011
Posted by fofo in Silverlight, Silverlight 4, Silverlight-enabled WCF Service, WCF Service.Tags: Silverlight-enabled WCF Service, WCF Service
1 comment so far
In this post I would like to present in detail how we can consume WCF services from a Silverlight 4 application.I strongly suggest that you have a look in this post of mine where I talk about using web services – .asmx services and how we consme them in our Silverlight applications.I do advise against using .asmx web services in Silverlight application.WCF is strongly recommended by Microsoft and is the distributed technology that MS supports and will continue to support and enhance.In many cases you will see a difference in performance.WCF is significantly faster.Have a look in this very useful article in MSDN where it compares performance of WCF distributed systems with other existing distributed technologies.
All the tools you need to get you started with Silverlight ( and to follow this example) can be found here. Make sure you download and install everything. You will need Visual Studio 2010 or Visual Web Developer Express edition with Microsoft Silverlight 4 Tools for Visual Studio 2010.
I have Visual Studio 2010 Ultimate edition installed in my machine and that is I am going to use.
1) Launch Visual Studio and create a new project a Silverlight application.Give it an appropriate name.I have named it SilverlightWCFService. Make sure you click the option where you host the Silverlight application in a new web site.The Silverlight version should be 4.I will use C# as the development language.
2) I am not going to look into WCF in detail. I can only say a few things. Microsoft with .Net 3.0 Framework, introduced WCF. WCF is Microsoft’s choice to design/build Service Oriented Architecture applications. In this example the silverlght client will use a WCF data service to work with the data.Add a new item to your Web hosting project.Select the project and right click on it. Choose Add new item and from the available templates choose Silverlight-enabled WCF Service.I have named it ProductsByCategory.svc.Have a look at the picture below.
This will build us a service that is correctly configured for Silverlight.Do not choose the WCF Service template.As I have said earlier, Microsoft suggests that WCF is the best way of writing services when a Silvelight application is involved.So Microsoft has provided us with a template that is specifically configured for Silverlight.Typically built-in WCF Services do not work out of the box for Silverlight.You cannot have any kind of bindings with Silverlight.You cannot have any type of ws*.Binding should be set to BasicHttpBinding.
3) Obviously we need to add a data source, a database. I will use the Northwind database.If you need the installation scripts for the sample Northwind database, click here. I assume that you have access to a version of SQL Server.If you do not, you can download and install the free SQL Server Express edition from here.
4) I assume that you probably have some experience on working with Entity Framework.With EF we can create easily data-centric applications.Entity Framework is an object-relational mapping (ORM) framework for the .NET Framework.EF addresses the problem of Object-relational impedance mismatch. I will not be talking about that mismatch because it is well documented in many sites on the Internet. Through that framework we can program against a conceptual application model instead of programming directly against a relational schema-model. By doing so we can decrease the amount of code we do write to access a data storage and thus decrease maintenance time.
We will need to add an ADO.Net Entity Data model to our project.
In order to see how I am going to accomplish that, have a look in this post (this is my other blog).You can follow steps 5-9.Ι am going to adopt the database first approach.The only difference is that you should pick Northwind database instead of AdventureWorksLT.In the model we only need the Categories,Suppliers,Products tables.So pick only those tables and close the Entity Data Model wizard.My final model in the Entity Designer looks something like this
5) Now we are ready to write a method in our service class that gets the Products By Category.Have a look at the ProductsByCategory.svc.cs file.The Silverlight code will call the WCF service to request the data from the database.This is the code I wrote for the WCF Service.You have to mark the method you wrote with “[OperationContract] ” .
public class ProductsByCategory
{
[OperationContract]
public List<Product> GetProductsByCategory(string categoryname)
{
var ctx = new NorthwindEntities();
var query = from product in ctx.Products
where product.Category.CategoryName == categoryname
select product;
return query.ToList();
}
// Add more operations here and mark them with [OperationContract]
}
6) Now that we have our WCF service ready we can add a Service Reference from the Silverlight application.Select the Silverlight project and right click on it. Choose Add Service Reference.Click Discover to find available services. You will find the available service and then select it.You will see all the methods available in it.I choose to have a new namespace “MyServices”.Finally click OK.Have a look at the picture below. It will also show you the steps Ι followed.
This whole process generates the necessary proxy and data contract classes that are necessary to talk to the web service.Our Silverlight application knows all about the WCF service up to this point.I would urge you to have a look in the Reference.cs file in the Silvelight project. You can find this file if you choose “Show All files” from the Solution Explorer. Have a look at the picture below to see where it is located.
7) Now we have to design our user interface and also write the necessary code for the data binding. We have to open the MainPage.xaml file and type the following.
<Grid Background="Cyan">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="ProductList"
Margin="12 12 12 12 "
DisplayMemberPath="ProductName" />
<Border BorderBrush="#D92B2B"
Background="Gray"
BorderThickness="3"
Padding="10"
Margin="10 10"
Grid.Column="1">
<StackPanel DataContext="{Binding SelectedItem, ElementName=ProductList}" Background="#FF47CE52">
<TextBlock>Product Name</TextBlock>
<TextBox Text="{Binding ProductName, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
<TextBlock>Unit Price</TextBlock>
<TextBox Text="{Binding UnitPrice, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
<TextBlock>Discontinued</TextBlock>
<TextBox Text="{Binding Discontinued, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
</StackPanel>
</Border>
</Grid>
I have a ListBox control and displays the names of the Products.In a seperate StackPanel element I have 3 textblock and 3 textbox elements.Inside the textbox elements I am going to bind data fetched from the WCF service.More specifically I am interested in the ProductName,UnitPrice,Discontinued properties/fields. I am not going to go into details as far as data binding is concerned. We have the FrameworkElement (StackPanel) that we want to link it to the datasource.The DataContext property sets the data context for that element.If you want to learn more about the issue click here .
8) Now we need to write the code in the MainPage.xaml.cs file.We have to populate the ProductList element with data.We are going to write some code in the MainPage_Loaded event handling routine.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var clnt = new ProductsByCategoryClient();
clnt.GetProductsByCategoryCompleted += (t, r) =>
{
if (!r.Cancelled && r.Error == null)
{
ProductList.ItemsSource = r.Result;
}
else
{
MessageBox.Show("There is no data");
}
};
clnt.GetProductsByCategoryAsync("Refreshments");
}
}
We must instantiate an instance of the client before we can use the service ( var clnt = new ProductsByCategoryClient(); ).
We have two members for the GetProductsByCategory operation. We have the asynchronous method and the completed event.I am handling the completed event first. I am going to use a lambda expression. First I check that the operation has not been cancelled.Then I bind the results to the ProductList element.
Finally I hard code the category, I execute the call in which the products I am interested to bring into the silverlight client belong ( clnt.GetProductsByCategoryAsync(“Refreshments”); ).
Build and Run your application and see all the products appearing in the silverlight client fetched from the WCF service.
That is all folks. Stay tuned because I am going to post more examples on Silverlight 4.
Email me if you need the source code.
Hope it helps!!!
Using ASP.Net web services in Silverlight 4 applications November 20, 2011
Posted by fofo in Silverlight, Silverlight 4.Tags: Silverlight, Silverlight 4.0, web services
3 comments
In this post I would like to present in detail how we can consume .asmx web services from a Silverlight 4 application. Silverlight supports and “recognises” web services in a similar way that ASP.Net applications can “talk” to web services. One might say that .asmx web services are considered by Microsoft legacy software. I will not disagree with that. Sometimes we do not have the luxury (time or budget) to create the services from scratch. It is very difficult to convince your boss or client to create a WCF service that does something when the functionality already exists in a web service (.asmx). So if now, I have the chance to write a whole Silverlight application from scratch I would not use .asmx web services, I would use WCF. But as I said before we have to use and maintain legacy code.
All the tools you need to get you started with Silverlight ( and to follow this example) can be found here. Make sure you download and install everything. You will need Visual Studio 2010 or Visual Web Developer Express edition with Microsoft Silverlight 4 Tools for Visual Studio 2010.
I have Visual Studio 2010 Ultimate edition installed in my machine and that is I am going to use.
1) Launch Visual Studio and create a new project a Silverlight application.Give it an appropriate name.I have named it SilverlightWebService. Make sure you click the option where you host the Silverlight application in a new web site.The Silverlight version should be 4.I will use C# as the development language.
2) Add a new web service to the asp.net hosting project (SilverlightWebService.Web). I have named it CategoryProducts.asmx. If you notice in the .asmx.cs file that inherits from the WebService class there are web methods that can be executed over the web.
3) Obviously we need to add a data source, a database. I will use the Northwind database.If you need the installation scripts for the sample Northwind database, click here
4) We will need an ADO.Net Entity Data model to our project. In order to see how I am going to accomplish that, have a look in this post (this is my other blog).You can follow steps 5-9. The only difference is that you should pick Northwind database instead of AdventureWorksLT.In the model we only need the Categories,Suppliers,Products tables.My model in the Entity Designer looks something like this
5) So let’s write a method in our service class that gets the Products By Category.
[WebMethod]
public List<Product> GetProductsByCategory(string categoryname)
{
var ctx = new NorthwindEntities();
var query = from product in ctx.Products
where product.Category.CategoryName == categoryname
select product;
return query.ToList();
}
This is a very easy to follow code.I am creating a method that returns a List of Product entities that takes as an input parameter the category that the product belongs.I am just building a simple Linq to Entities query.
Make sure you test the web service and that it functions correctly.
6) Now we need to add a reference from our silverlight application to the web service.Select the Silverlight project and right click on it. Choose Add Service Reference.Click Discover to find available services. You will find the available service and then select it.You will see all the methods available in it.I choose to have a new namespace “MyServices”.Finally click OK. This whole process generates the necessary proxy classes that are necessary to talk to the web service.
In my case it looks like the picture below.
Have a look at the files being generated.You can have a look at the Reference.cs file.You should see that some classes are generated and the interfaces they support.
7) Now we have to design our user interface. We have to open the MainPage.xaml file and type the following.
<Grid
Background="Cyan">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="ProductList"
Margin="12 12 12 12 "
DisplayMemberPath="ProductName" />
<Border BorderBrush="#D92B2B"
Background="Gray"
BorderThickness="3"
Padding="10"
Margin="10 10"
Grid.Column="1">
<StackPanel DataContext="{Binding SelectedItem, ElementName=ProductList}" Background="#FF47CE52">
<TextBlock>Product Name</TextBlock>
<TextBox Text="{Binding ProductName, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
<TextBlock>Unit Price</TextBlock>
<TextBox Text="{Binding UnitPrice, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
<TextBlock>Discontinued</TextBlock>
<TextBox Text="{Binding Discontinued, Mode=TwoWay,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}" />
</StackPanel>
</Border>
</Grid>
I have a ListBox control and displays the names of the Products.In a seperate StackPanel element I have 3 textblock and 3 textbox elements.Inside the textbox elements I am going to bind data.More specifically I am interested in the ProductName,UnitPrice,Discontinued properties/fields.
I am not going to go into details as far as Data binding is concerned. We have the FrameworkElement (StackPanel) that we want to link it to the datasource.The DataContext property sets the data context for that element.
If you want to learn more about the issue click here .
8) Now we need to write the code in the MainPage.xaml.cs file.We have to populate the ProductList element with data.We are going to write some code in the MainPage_Loaded event handling routine.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Loaded +=new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender , RoutedEventArgs e)
{
var clnt = new GategoryProductsSoapClient();
clnt.GetProductsByCategoryCompleted += (t, r) =>
{
if (!r.Cancelled && r.Error == null)
{
var result = r.Result;
ProductList.ItemsSource = result;
}
else
{
MessageBox.Show("There is no data");
}
};
clnt.GetProductsByCategoryAsync("Refreshments");
}
}
We instaniate the web service proxy before we can use the service ( var clnt = new GategoryProductsSoapClient(); ).
The web service calls in Silverlight are asynchronous.We have two members for the GetProductsByCategory operation. We have the asynchronous method and the completed event.I am handling the completed event first. I am going to use a lambda expression. First I check that the operation has not been cancelled.Then I bind the results to the ProductList element.
Finally I hard code the category, I execute the call in which the products I am interested to bring into the silverlight client belong ( clnt.GetProductsByCategoryAsync(“Refreshments”); ).
Build and Run your application and see all the products appearing in the silverlight client from the web service.
That is all folks. Stay tuned because I am going to post more examples on Silverlight 4.
Email me if you need the source code.
Hope it helps!!!

















