Placing controls in the top row
I want to place a Textblock (for the prompt) and TextBox (for input) and a button in the top row. The easiest way to do so is with a stack panel, and I'll surround it all with a border to set it off from the results.
<Border BorderBrush="Black" BorderThickness="2" Grid.Row="1" Grid.Column="1"/>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="Last name to search for: " VerticalAlignment="Bottom"
FontSize="18" Margin="15,0,0,0" />
<TextBox x:Name="LastName" Width="250" Height="30" Margin="2,0,0,4"
VerticalAlignment="Bottom"/>
<Button x:Name="Search" Width="75" Height="30"
Margin="20,0,0,4" Content="Search"
VerticalAlignment="Bottom" Background="Blue" FontWeight="Bold"
FontSize="14" />
</StackPanel>
Finally, drag a DataGrid from the Toolbox onto the XAML.
<my:DataGrid x:Name="theDataGrid" AlternatingRowBackground="Beige" AutoGenerateColumns="True" Width="700" Height="500" Grid.Row="2" Grid.Column="1" CanUserResizeColumns="True" />
You'll notice that it is given the prefix my and that a new namespace is declared to support it,
xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
Write the Event Handler for the Search Button
When the user clicks the search button we want to pick up the text in the Text box and give it to the web service, and get back a collection of customers. Let's set up the boilerplate event handling code in page.xaml.cs,
public Page()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
Search.Click += new RoutedEventHandler(Search_Click);
}
void Search_Click(object sender, RoutedEventArgs e)
{
}
Call the Service Asynchronously
The only way to call a web service from Silverlight is asynchronously (which is fair as it is running in a browser and can't afford to block!)
The first task is to get a reference to the Web Service's Service1Client member. You can examine this in the object browser to see that it is this object that has the Asynchronous methods we'll need,

Figure 3-14. The Web Service client seen in the object browser (Click to view full-size image)
(image slightly abridged to save space)
We assign the Service1Client to the local object webService,
void Search_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client webService =
new SQLData.ServiceReference1.Service1Client();
We then use webService to set up an event handler for the method that will be called when the GetCustomersByLastNameCompleted event is called
webService.GetCustomersByLastNameCompleted +=
new EventHandler<SQLData.ServiceReference1.
GetCustomersByLastNameCompletedEventArgs>
(webService_GetCustomersByLastNameCompleted);
Finally, we make the asynchronous call
webService.GetCustomersByLastNameAsync(LastName.Text);
}
When the service completes, the GetCustomersByLastNameCompleted event is raised, and our method is invoked. The carefully constructed list of Customers is stashed in e.Result which we assign to the DataGrid's ItemSource property and all the bindings now have a source to bind to.
void webService_GetCustomersByLastNameCompleted(
object sender,
SQLData.ServiceReference1.GetCustomersByLastNameCompletedEventArgs e)
{
theDataGrid.ItemsSource = e.Result;
}
Figure 3-15. The Running Program (Click to view full-size image)