|
|
by Naveen
10. March 2010 10:14
Download Sample Projects (114.64 kb)
Quite some time back I wrote about
How to use HttpWebRequest to send POST request to another web server in ASP.Net
applications. Now that a lot of silverlight applications are being developed, we have
similar need to post data from silverlight applications. The concept is exactly the
same that I used in ASP.Net. But there is little difference. Silverlight does not allow
blocking synchronous requests. All web requests are asynchronous. That means we have
little bit more book keeping to do and manage the thread contexts etc. to make sure
that then requests complete and we need to do any UI work in call back methods, we
stay in correct thread context.
To keep example simple, I am going to post two values to destination URL using POST
method. In the attached project, on Slots.xaml page, I have added a simple
button Submit Data. And in the event handler of this button, I initiated request
to submit data to Default page of sample web application. The event handler for the
click looks as below.
private void SubmitData_Click(object sender, RoutedEventArgs e)
{
// Prepare web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create("http://localhost/SilverGridWeb/Default.aspx");
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), myRequest);
}
This code is pretty much same as what I had in ASP.Net application. There is one difference.
Instead of calling GetRequestStream method, you will need to call
BeginGetRequestStream. This will initiate an asynchronous request. There
are two parameters that are passed to this method. First is the callback method that
needs to be called when this method completes. Second parameter is any object that you want
to pass to callback method. So here I have passed my HttpWebRequest object itself.
Now lets look at what is this callback method GetRequestStreamCallback. I copied
the function from Microsoft documentation itself and made some changes to fit my needs.
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
System.IO.Stream postStream = request.EndGetRequestStream(asynchronousResult);
string strId = "My Id";
string strName = "My Name";
string postData = "userid=" + strId;
postData += ("&username=" + strName);
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
You can see that in callback method, I grabbed the request object that was passed as
state to the method call. Then I constructed data that I need to pass with the request
that needed to be sent as POST. And then made another async call BeginGetResponse
to submit the data and get the response.
Now lets look at what is this callback method for response.
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
Action<string> act = new Action<string>(DisplayResponse);
this.Dispatcher.BeginInvoke(act, responseString);
}
void DisplayResponse(string msg)
{
GainersText.Text = msg;
}
Again I passed original HttpWebRequest object to the call method as state. In
the call back method, you can grab the request object and then call EndGetResponse
to get the resonse stream.
Thread Context and Invalid cross-thread access error
You will notice that in GetResponseCallback method I have called BeginInvoke
method on Dispatcher thread. This is very important if you are planning on doing
any UI manipulation in the call back methods. The call back methods are invoked on a thread
that are separate from the UI thread that initiated the request. So if you try to
access any UI element in this callback you will get the following exception thrown.
An unhandled exception ('Unhandled Error in Silverlight Application
Code: 4004
Category: ManagedRuntimeError
Message: System.UnauthorizedAccessException: Invalid cross-thread access.
at MS.Internal.XcpImports.CheckThread()
at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value,
Boolean allowReadOnlySet, Boolean isSetByStyle, Boolean isSetByBuiltInStyle,
PropertyInvalidationReason reason)
at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Controls.TextBlock.set_Text(String value)
at SilverGrid.Views.Stocks.GetResponseCallback(IAsyncResult asynchronousResult)
at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClassd.
<InvokeGetResponseCallback>b__b(Object state2)
at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,
ContextCallback callback, Object state)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal
(_ThreadPoolWaitCallback tpWaitCallBack)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
') occurred in iexplore.exe [7532].
Therefore it is important that from the callback method, you invoke an action request
on Dispatcher thread of UI.
by Naveen
9. March 2010 08:37
Here is some error that most of Silverlight developers run into at some point.
An error occurred while trying to make a request to URI
'http://nave-pc/SilverGridWeb/GridDataService.asmx'.
This could be due to attempting to access a service in a cross-domain way
without a proper cross-domain policy in place, or a policy that is unsuitable
for SOAP services. You may need to contact the owner of the service to publish
a cross-domain policy file and to ensure it allows SOAP-related
HTTP headers to be sent. This error may also be caused by using internal types
in the web service proxy without using the InternalsVisibleToAttribute attribute.
Please see the inner exception for more details.
I had developed cross-domain access web services for Silverlight in the past and all
work like a charm. This morning I ran into this issue again while developing a new
web service for a new Silverlight application. I knew that I needed to add
CrossDomain.xml or ClientAccessPolicy.xml at root
of my web application. So I copied those files from existing application to this new one.
To my surprise it did not resolve the issue. I tried all kind of tricks and options
but nothing seemed to help. Finally I decided to look at Silverlight documentation and
see if there is anything new that has been done for Silverlight 3. Last time I did this
was for a Silverlight 2.0 application. I could not find anything different in the
description of what needed to be done. But then there was something in the sample
XML file content for these files that caught my eye and looked different that what I had.
<allow-from http-request-headers="SOAPAction" >
Notice the underlined section. Previously the value in the allowed headers used to be *.
Well, that does not seem to work any more. So I replaced it and everything worked fine.
There are some other important points I am going to discuss in this post. A lot of users
do not seem to be clear where these cross domain policy files should be placed.
Location of CrossDomain.xml and ClientAccessPolicy.xml
As the documentation states, these should be placed at the root of the application. Although
the statement is very clear but it causes lot of confusion about what is root? There are two
ways you create a site in IIS, Virtual Directory and Web Application.
So if you have a web site foo.com created as a web site in IIS, then the folder containing the
content of this site is root of the application. So your policy files go in that folder. If you have
created a virtual directory Bar under this web site where your web service is hosted,
then the root of the site is still foo.com and not foo.com/bar. To
verify it, open IIS log of your application and look for entries for Crossdomain.xml and
ClientAccessPolicy.xml. From those entries you can figure out where those files
should be located. If the caller is not finding those files, then you should 404
errors in your log file. For example here are entries from my log file.
1.17.30.170 GET /clientaccesspolicy.xml - 80 - 1.17.30.162 404 0 2 1
1.17.30.170 GET /crossdomain.xml - 80 - 1.17.30.162 404 0 2 1
This is very important. If you are hosting your web service in a web application that is created as a
virtual directory in Default Web Site then you need to copy these files in
wwwroot folder or whatver folder is configured to be default folder for your
IIS installation. Copying policy files in your virtual directory is not going to help. You
can also verify the location by looking at traffic in fiddler for your web service access.
Content for CrossDomain.xml and ClientAccessPolicy.xml
I have copied the content of these two files below. These files work for me on my my servers for
cross domain access from silverlight.
ClientAccessPolicy.xml
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction ">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
CrossDomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="SOAPAction,Content-Type"/>
</cross-domain-policy>
by Naveen
3. March 2010 11:49
Download Sample Projects (28.22 kb)
In my previous post,
How to set silverlight column chart style programatically", I discussed one of the customizations of chart styles.
In this post I will discuss one more customization of Silverlight charts rendering. This is about customizing
display of Tooltip display on charts. If you look at default tool tip display, they are limited
to displaying some combination of Independent and Dependent value. In some cases, that information is sufficient. But
you may have cases where you want your tool tips to be verbose to convey more information about the data point
that was used to render that point or column etc.
Template is the key
First and foremost concept that you will need to understand is how a chart actually gets rendered. Who
decided the layout of various components of a chart display. Like any other Silverlight control, its the
control template that defines how to chart is going to be rendered. So to customize the dispplay of
Silverlight control, you can create a new template or take the default template and make modifications to it
to come up with your own display scheme. Now you are asking from where can you get the default template for
various chart types. The answer to it is Silverlight Toolkit source code.
If you look in Charting/DataPoint folder of Controls.DataVisualization.Toolkit project, you will
find template files for all chart types.
Customize Tooltip For Chart
Let us get started. For this discussion I picked Column type chart. Here are the steps that I
followed to create a new template file for my column charts.
- Add a new resource dictionary file in your project. In sample project I added ColumnChartStyle.xaml
file under Assets folder.
- Open ColumnDataPoint.xaml file from DataPoint folder from tool kit source. Copy the content
of this file into your resource file.
- Make sure that you change the build action of your resource file to Resource from Page
- Assign a key to your style as shown below. You can pick any unique name. You are going to use
the key when we apply this new template and style to our column charts.
<Style TargetType="charting:ColumnDataPoint" x:Key="ByteBlocksColumns">
-
Open the XAML file where you have added chart that you want to display. In the sample project, it is in
Home.xaml. And then assign DataPointStyle property to point to the static resource that
we created from default implementation of ColumnDataPoint. And make sure that you use the key name that
you used in the resource file. Following snippet shows how I did it in sample project.
<chartingToolkit:Chart Title="Fruit Supply and Demand"
x:Name="FruitChart"
Width="500"
Height="350">
<chartingToolkit:Chart.Series>
<chartingToolkit:ColumnSeries
DataPointStyle="{StaticResource ByteBlocksColumns}"
Title="Fruit Supply"
IndependentValueBinding="{Binding Name}"
DependentValueBinding="{Binding Supply}"/>
</chartingToolkit:Chart.Series>
</chartingToolkit:Chart>
Now you should be able to compile and run your project. We have not done any customization of tool tip yet.
At this point you should be able to run the project with default template.
TooltipService and Tooltip
If you look near bottom of ColumnChartStyle.xaml file, you will find following snippet of code.
<ToolTipService.ToolTip>
<ContentControl Content="{TemplateBinding FormattedDependentValue}"/>
</ToolTipService.ToolTip>
This is default implementation of how and what is displayed in tool tip. So you can see that by default
only DependentValue is displayed. So this is the place where you will need to make changes
to customize the display of tooltip for chart. If you are only interested in making some minor changes like
adding some static text or adding display of dependent value as well, you can make a change as below.
<ToolTipService.ToolTip>
<StackPanel Orientation="Horizonal">
<ContentControl Content="{TemplateBinding FormattedDependentValue}"/>
<TextBlock Text="-" />
<ContentControl Content="{TemplateBinding FormattedIndependentValue}"/>
</StackPanel Orientation="Horizonal">
</ToolTipService.ToolTip>
Customizing Tooltip Display at run time
In the sample project, I have implemented a use case where I want to create tool tip display at run time.
What this means is that content of tool tip is being constructed based on some input from the
existing data that is bound to that column. So in the template I am going to make some changes as
shown below.
<ToolTipService.ToolTip>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{Binding Id, Converter={StaticResource FruitConverter}}"/>
</StackPanel>
</ToolTipService.ToolTip>
In the snippet above you will see use of two things. One is that I am binding the content to the actual
data object that was used to render that point. Second is use of converter. I am passing "Id" of the
object as parameter to the converter. And in the converter I do some mock query to get more data. Following
code shows how I constructed text of tool tip.
public class FruitSupplyToolTipConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return GetToolTip(int.Parse(value.ToString()));
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
object GetToolTip(int id)
{
var supply = MockData.FruitSupply.GetSupply();
var query = from item in supply where item.Id == id select item;
var items = query.ToList();
if (items.Count == 0)
{
return string.Empty;
}
return CreateToolTip(items[0]);
}
object CreateToolTip(FruitSupply supply)
{
var panel = new StackPanel();
panel.Orientation = Orientation.Vertical;
var tipTextBlock = new TextBlock();
tipTextBlock.Inlines.Add(new Run { Text = supply.Name });
tipTextBlock.Inlines.Add(new LineBreak());
tipTextBlock.Inlines.Add(new Run { Text = string.Format("Supply: {0}", supply.Supply)});
tipTextBlock.Inlines.Add(new LineBreak());
panel.Children.Add(tipTextBlock);
var hlink = new HyperlinkButton();
hlink.Content = "For more informattion Goto http://www.ByteBlocks.com";
hlink.NavigateUri = new Uri("http://www.byteblocks.com");
panel.Children.Add(hlink);
return panel;
}
}
You could argue that instead of going to the extent of using converter to build a tool tip text,
I could have added another property to data object that contains the text and then bind
tool tip to that property. That would have worked perfectly as well. But for demonstrating
how you can construct tool tip text based on some other pieces of data or if tool tip content
changes rapidly with time as well, then you need to access it at run time.
I hope this should give you good starting point to go nuts on more nifty tool tips.
by Naveen
24. February 2010 10:23
Download Sample Project (367.89 kb)
In one of my previous posts
How to use DataGrid in Silverlight
I showed a very simple usage where data grid was bound to a list of products. Now let us take one more step
in customizing use of this data grid. When I executed my method to get list of products from
AdventureWorks database, it returned me about 1000 records. And then datagrid was bound
to that list, i got a huge page with grid showing all the records. I am sure at this point you are
looking for way to add some kind of paging to your data grid so that user can navigate the list
easily.
Silverlight has a control named DataPager that comes in very handy to add
paging functionality to any control that you use to display lists. From the name
is it obvious that this control is a pager. Following XAML shows how I added paging functionality
to my datagrid.
<StackPanel x:Name="ContentStackPanel" Orientation="Vertical">
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
Text="Products"/>
<data:DataPager x:Name="ProductsPager"
PageSize="10"
DisplayMode="Numeric"
AutoEllipsis="True"
HorizontalAlignment="Left" />
<data:DataGrid x:Name="ProductsGrid">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn>
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Button x:Name="UpdateButton" Content="Update"
Click="UpdateButton_Click"></Button>
</StackPanel>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
You can read more about different ways to customize the display of datapager from the documentation. For
this discussion you can see that I have set PageSize, DisplayMode, AutoEipsis and HorizontalAlignment
properties of pager and the screen shot shows how it looks. I will talk more about customization of
DataPager in detail in next post. For now I just want to keep it to simple use.
PageViewCollection
This is the collection object that drives the functionality for DataPager. In general you need a collection
that implements IPagedViewCollection interface. No, you do not have to do any more implementation
to get DataPager to work. We already have list of products obtained from previous web service call. You can
simply wrap that list into PagedViewCollection object and set it as Source
for DataPager object. And then set the source for DataGrid as this PagedViewCollection
object and we are all set to go. Following code shows simple change I made in code from previous sample
project.
void GetProductsCompleted(object sender, GetProductsCompletedEventArgs e)
{
_products = e.Result;
if (null != _products)
{
_pagedProductsView = new PagedCollectionView(_products);
ProductsPager.Source = _pagedProductsView;
ProductsGrid.ItemsSource = _pagedProductsView;
}
}
Add References
PagedViewCollection is defined in System.Windows.Data assembly.
So you will need to add reference to this assembly in your Silverlight project and then
add using directive for the namespace in your source code to refer to the
classes in this namespace and assembly.
Adding Paging to DataGrid in Silverlight is as easy as that.
by Naveen
11. February 2010 15:36
Download Sample Project
In the previous post How to use Silverlight DataGrid I discussed simple use of DataGrid in Silverlight application. Now it is time to start putting together implementation that we have from day to day to applications. One of the tasks that you may come across is that you need to add buttons to each row in the
DataGrid and then handle click events for those buttons. In the previous post I mentioned use of DataGridTemplateColumn to provide custom rendering of columns in the grid. So to add button(s) to your column, you will use the template column and then provide Button control to add them to each row. Following snippet shows how it looks like in my sample application.
<data:DataGrid x:Name="ProductsGrid">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn>
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Button x:Name="UpdateButton" Content="Update"
Click="UpdateButton_Click"></Button>
</StackPanel>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
Handling Click Event For Button In DataGrid
As you can see from the XAML above, I just added handling of Click event on Button control. And in the codebehind provided implementation for it.
private void UpdateButton_Click(object sender, RoutedEventArgs e)
{
var ctl = e.OriginalSource as Button;
if (null != ctl)
{
var product = ctl.DataContext as Product;
if (null != product)
{
var msg = string.Format("{0}, {1}, {2}",
product.ProductID, product.Name, product.ListPrice);
MessageBox.Show(msg);
}
}
}
Accessing Data Associated With Row In DataGrid
When user clicks on the button in datagrid row, the method gets called. Next question you have is how do you access the data associated with the row on which button was clicked. It is very straight forward. When DataGrid rendering takes place, each control in the row is bound to DataContext. This DataContext is the data that was used to render that row. So you simple look at DataContext property of Button control that raised the event and got the actual data object used for that row.
I think this should give you a good starting point on how to add buttons or some other controls in DataGrid rows and how to access data for them as well. In next post I will discuss more of customization of Silverlight DataGrid.
by Naveen
5. February 2010 06:58
DataGrid is one of the most important control when it comes to displaying tabular kind of data. We all implement rendering of such data in some of table format. Developers who has been using ASP.Net are very familiar with controls like DataGrid and GridView.
Good news is that there is equivalent DataGrid control for Silverlight as well. And for most part
it is used the same way as you do in ASP.Net but with different syntax and different way of customizing
display of it. In this post I am going to show a very plain and simple use of DataGrid control
in Silverlight and then in subsequent posts I will build on top of this post to show some more
advanced uses of DataGrid control.
Silverlight Tool Kit
You may already know this and already has it on your development machine, but I will mention it for
sake of completness. You are going to need
Silverlight Toolkit to
use DataGrid. Yes, the control is not part of core Silverlight. Microsoft has
developed it as part of the tool kit that has lot of usefull controls. You can read more about this
tool kit and controls on the site. For now, down the toolkit and install it on your machine.
Reference assemblies
In your Silverlight project, you will need to add reference to System.Windows.Controls.Data
assembly. This is the assembly where DataGrid control is defined. Now you can include DataGrid control
on your XAML file. If you tried to add mark up like below on your page, you are going to get error telling you
that DataGrid is not recoganized.
<DataGrid x:Name="MyGrid" />
You have to treat DataGrid control like a UserControl in ASP.Net where you have to specify
a tag prefix and assembly on top of your page to indicate use of that control. In Silverllight you do this
my including xml namespace tag for that silverlight control. In my case I have the following
xmlns entry on my XAML file.
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
This tells the application that I am going to use prefix data for the controls
that are present in assembly System.Windows.Controls.Data. Based on this you can
now add the following like of mark up on XAML file to include DataGrid on your page.
<data:DataGrid
x:Name="CommentsGrid"
Height="300"
AutoGenerateColumns="True"
IsReadOnly="True">
</data:Grid>
Attach To Data Source
Now that we have included DataGrid control on the page, we need to attach it to some
data source to show some results. Very much like ASP.Net, you will attach an enumeration to this
control. The difference is that here it is done through property name ItemSource.
Following line of code shows how it is done for silverlight DataGrid control.
List<Comment> unmoderatedComments = new List<Comment>();
void BindGrid()
{
CommentsGrid.ItemsSource = unmoderatedComments;
}
As you can see that DataGrid is bound to a List of Comment objects. So far so good, very much
like your ASP.Net DataGrid or GridView.
Columns to Display
In the mark of DataGrid above, I have explcitly set AutoGenerateColumn property to
true. This actually is default value. What this means is that when DataGrid is bound to the
collection, it will generate column for each data field or property for the objects in the collection
and display them. Thsi is same behavior you see in ASP.Net data grid.
Explcitly specifying Columns
When you are dealing with some real application most of the time you control the columns
you want to display and how you want to display them. Silverlight DataGrid does allow you to
do so. Fisrt, you will set AutoGenerateColumns property to false. Following
mark up shows how you will specify the columns that you want to display.
<data:DataGrid x:Name="CommentsGrid" Height="300"
AutoGenerateColumns="False" IsReadOnly="True">
<data:DataGrid.CellStyle>
<Style TargetType="data:DataGridCell">
<Setter Property="VerticalAlignment" Value="Top"></Setter>
</Style>
</data:DataGrid.CellStyle>
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Comment Date"
Binding="{Binding CommentDate}"></data:DataGridTextColumn>
<data:DataGridTextColumn Header="Comment Text" Binding="{Binding Text}">
<data:DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</data:DataGridTextColumn.ElementStyle>
</data:DataGridTextColumn>
<data:DataGridTemplateColumn>
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button x:Name="ApprovedButton" Content="Approved"
Click="ApprovedButton_Click" Height="30" Margin="3"></Button>
<Button x:Name="DeleteButton" Content="Delete"
Click="DeleteButton_Click" Height="30" Margin="3"></Button>
<Button x:Name="SpamButton" Content="Mark Spam"
Click="SpamButton_Click" Height="30" Margin="3"></Button>
</StackPanel>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
You will need to add Columns section under your DataGrid control definition
and then specify each column that you would want to display. And to bind the column to
particular property or field, you will use Binding property. For this post
I am going to keep the dicussion to simple binding of the column to property of the
object. I will discuss more advanced use in subsequent posts. You can see it is
very similar to how you are used to doing things in ASP.Net.
And to accomodate more customized view of the column, you will use DataGridTemplateColumn
where you can layout the template of the view of that column. This is also
similar to template column in ASP.Net.
More...
For this post I am going to leave this discussion to this simple display of data. I will be discussing more
about use of Silverlight DataGrid in subsequent posts. This post should get you started with use of
it now.
by Naveen
7. January 2010 17:25
Default rendering of Bing Map Silverlight Control displays few of the in-built controls like Copyright, Scale, Navigation, Logo etc. If you are not interested in displaying any of these controls, you can simply hide it by setting their visibility. Following code snippet shows how to hide these navigation controls.
void SetMapForgroundMembers()
{
UserLocationsMap.NavigationVisibility = System.Windows.Visibility.Collapsed;
UserLocationsMap.LogoVisibility = Visibility.Collapsed;
UserLocationsMap.CopyrightVisibility = System.Windows.Visibility.Collapsed;
UserLocationsMap.ScaleVisibility = System.Windows.Visibility.Collapsed;
} }
by Naveen
6. January 2010 07:35
In one of my earlier posts
Convert IP Addresss To Geo Location, I discussed how you can query a web service or database to get
geo-location of that internet service provider. Now what do you do with that geo-location or spatial information. For one of
the current Data Visualization projects I am working on, I had to show these locations on the map as well. The
application is a Silverlight application so obvious choice was to find a control or component that I could
drop in silverlight. And you pretty much have the answer, Use Bing Map Silverlight Control.
In this post I am going to discuss some of the following topics.
- How to use Bing Silverlight Map Control?
- How to add push pins to bing map?
- How to add legends or some text to Silverlight Bing Map?
- How to add regular silverlight controls on Bing Map control?
The documentation for Bing Map Silverlight control is still maturing and lacks lot of details. So most of the
discussion in this post is based on personal experience and conversations I had through news groups and forums.
Set up development enviroment
Before you can start developing your silverlight application using Bing Map Silverlight control, you will need to
do following things.
- Create a developer account at Bing portal
- As part of registration process, you will also be required to a credential key that is
used with each request that you send to Bing web service to access data.
- Download Bing Map Control SDK
and install on your development machine.
Create Project and lets roll
Microsoft has provided a good walk through on
Creating a Basic Application Using the Silverlight Map Control. I will strongly recomment going through
it if its first time for you in Bing Map development.
Adding PushPin to Bing Map
Now that you have a vanilla implementation of map showing in your application. Next I want to add indicztors
on the map to show location of internet service providers for which I have geo corodinates. There are
few ways you can do. The most basic thing that you need to keep in mind is that Bing Map control is like any
other silverlight control and can act as a container for other silverlight control. That means that I can just draw
any shapes or objects at given corodinates. Well, you got it. Bing Map SDK provides some of these
indicator controls out of the box. And one of them is PushPin. So what you need to do is
crate instances of PushPin objects, set their longitude and latitude and add them as children of
map control. Following code snippet shows how I added a collection of PushPin objects to
my map control.
foreach(var loc in locations)
{
var pp = new Pushpin()
{Location = new Location(loc.Latitude, loc.Longitude)};
UserLocationsMap.Children.Add(pp);
}
Adding DataGrid to Bing Map
Next task I had to do was to provide some summary of the data on the map itself. More precisely, I wanted to
show how many service provides from each country I have in my database. For demo purposes I just
needed to show name and count. I decided to add a DataGrid to map to show this data. Later
on I am going to handle click events in this grid to have some interaction with the map as well. Since
I already knew where I wanted to place the grid and what columns needed to be shown, I could just
add this through XAML file itself. Following XAML snippet from the application shows how I have
added a text block and data grid to Bing Map control as children.
<m:Map CredentialsProvider="xxxxxxxxxx" Name="UserLocationsMap">
<m:Map.Children>
<o:ShadowText x:Name="MapTitleText" ForegroundTop="Black" ForegroundBottom="Orange"
Text="ISP Locations" FontFamily="Verdana" FontSize="24"
HorizontalAlignment="Left" Margin="20,75,50,10"/>
<StackPanel x:Name="CountryListPanel" Margin="20,250,50,10" Orientation="Vertical">
<data:DataGrid x:Name="CountryCountGrid" Width="150" Height="250"
AutoGenerateColumns="False" HorizontalAlignment="Left">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Country" Width="SizeToHeader" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Count" Width="SizeToHeader" Binding="{Binding Count}" />
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
</m:Map.Children>
</m:Map>
Postioning on Map control
This is something you will have to play very close attention to. There is a difference between how
controls or objects placed on map control. You must have noticed that when I added PushPin
to map, I used longitude and latitude to position them on the
map. But when I added DataGrid and ShadowText controls, I used Margin
to control the placement. Most of the indiccator or layer objects that are provided in Bing Map SDK use
gro-location values (longitude and latitude) to place object. But when you add regular
silverlight controls on map, then you will control the position using Margin relative to origin of map control.
by Naveen
4. January 2010 14:31
Let me wish a happy new year to all our blog readers.
This is first post of year 2010 and I decided to write my favorite topic of all times, Data Analysis
and Visualization. These days I am working on a Silverlight application that involves
very extensive use of charts for data visualization. And I use charting controls provided by
Microsoft in Silverlight tool kit.
There are lot of examples available out there that shows you how to use these controls and how to
style them. When it comes to styling and things like that, majority of the examples are focused around
modifying control template or modifying styles in XAML file itself. Lot of time you make decisions about
the type of chart and style of chart at run time based on data that needs to be visualized.
In this post I am going to focus on following tasks:
- How to add a chart series programatically
- How to set style of chart series programtically
- How to set colors of columns in silveright charts programtically
Following image shows you a multi-series column chart. It shows three types of values at different intervals.
One of the driving factor behind adding the column series was that I did not know how
many different types of values are going to be returned in the data. So I could not simply add
X number of ColumnSeries on XAML to say that I need to draw multi-series column chart with
3 points or things like that.
Following code snippet shows how I added column series in the main chart controls and how I specified different
colors of the bars that are going to represent each type of data point.
foreach(LatencyColumnPlotData plotData in _latencyDataValues.ColumnPlotValues)
{
var series = new ColumnSeries();
var style = new Style(typeof (ColumnDataPoint));
SolidColorBrush bgBrush = (idx==1) ?
new SolidColorBrush(Colors.Blue) :
new SolidColorBrush(Colors.Orange);
var setterBg = new Setter(ColumnDataPoint.BackgroundProperty, bgBrush);
style.Setters.Add(setterBg);
series.DataPointStyle = style;
series.ItemsSource = plotData.DependentValues;
series.IndependentValueBinding = null;
series.Title = (idx == 1) ? "Average" : "Current";
idx++;
latencyChart.Series.Add(series);
}
var thresholdSeries = new ColumnSeries();
thresholdSeries.IndependentValueBinding = null;
thresholdSeries.ItemsSource = _latencyDataValues.ThresholdLatencyValues;
thresholdSeries.Title = "Threshold";
var bg =
new Setter(ColumnDataPoint.BackgroundProperty, new SolidColorBrush(Colors.Green));
var bgStyle = new Style(typeof(ColumnDataPoint));
bgStyle.Setters.Add(bg);
thresholdSeries.DataPointStyle = bgStyle;
latencyChart.Series.Add(thresholdSeries);
by Naveen
7. December 2009 06:23
In my previous post How to hide gridlines in charts,
I showed how you can accomplish the task from XAML. This is all good when you know that rendering behavior
of you chart is not going to change or you do not have to modify the display at run time based on some computed
values curing run time. And works great for design time as well. But a lot of time you want to change
the behavior at run time. In that case you need to know how you can change properties of axis programatically.
Each chart has a collection of Axis. By default this collection is empty. Charting controll fills this
collection if you do not provide any. And it makes it decision based on the type of values you render on these axis.
For example tf you are displaying DateTime type values on an axis, control will add DateTimeAxis to
its collection. I have two liner axis in my chart that display simple numeric values. Following code shows how
I added two linear axis, X and Y, to my chart. Most important property to set is Orientation. Without it,
rendering engine does not know what axis you intend to change.
private void SetYAxis()
{
var lax = new LinearAxis();
lax.ShowGridLines = false;
lax.Orientation = AxisOrientation.Y;
lax.Title = "Response Time";
myChart.Axes.Add(lax);
}
private void SetXAxis()
{
var lax = new LinearAxis()
{
ShowGridLines = false,
Title = "Interval",
FontWeight = FontWeights.Bold,
MaxHeight = 1,
Opacity = 0,
Orientation = AxisOrientation.X
};
myChart.Axes.Add(lax);
}
by Naveen
7. December 2009 05:53
This is one of the thing that is easy to do but no so obvious. I think mostly its lack of complete description of how charting controls provided in Silverlight toolkit work and how to manipulate them. When you draw charts like Line, Column, Bar etc., the grid line on DependentValue are rendered by default. There is a property ShowGridLines available on DisplayAxis class that is base class for axis. You just need to set its value to False. For example in my line chart I did not want to show grid lines on grid lines on Y axis. Following XAML snippets shows how I turned off rendering of grid lines on Y-axis.
<chartingToolkit:Chart Title="Latency" x:Name="latencyChart" BorderThickness="1">
<chartingToolkit:Chart.Series>
<chartingToolkit:LineSeries Title="Val 1"
DependentValueBinding="{Binding Threshold}"
IndependentValueBinding="{Binding IndependentValue}"
AnimationSequence="Simultaneous" />
<chartingToolkit:LineSeries Title="Val 2Latency"
DependentValueBinding="{Binding Current}"
IndependentValueBinding="{Binding IndependentValue}"
AnimationSequence="Simultaneous" />
<chartingToolkit:LineSeries Title="Val 3"
DependentValueBinding="{Binding Average}"
IndependentValueBinding="{Binding IndependentValue}"
AnimationSequence="Simultaneous" />
</chartingToolkit:Chart.Series>
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="Y" ShowGridLines="False"/>
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart
by Viper
8. October 2009 05:55
I was working on a silverlight form in an application. I was trying to add some validations and other related controls on the page. So I had added Label control on the page. I declared the xml namespace and associated tags at the top of the control file as well. When I tried to compile the application, I got the following error. I looked at the declarations, my SDK folder to make sure that I have the required SDK assemblies, I looked in GAC etc. Everything looked good and I still could not figure out what the problem is.
The tag 'Label' does not exist in XML namespace 'clr-namespace:System.Windows.Controls;assembly= System.Windows.Controls.Data.Input'
Could not load type 'Microsoft.Windows.Design.DataContextValueSourceAttribute' from assembly 'Microsoft.Windows.Design.Interaction, Version=3.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
What is the problem?
After spending good bit of time, I decided to look at one of the sample in SDK. I still could not figure out the issue. Then I decided to copy and paste the xml namespace and tags from the sample to my XAML file. Now everything worked fine. When I closely looked at the declaration, I saw the issue. See below, the one in red is wrong and one in green is good.
xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly= System.Windows.Controls.Data.Input"
xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"
You can see I had an extra white space after assembly=. It seems that compiler is literally parsing the string and trying to look for assembly file with name as is in the statement. Instead of giving error message that some namespace or control does not exist in the assembly, the correct error message should have been that assembly with name or path could not be found. I could not complain much either because I am using Visual Studio 2010 Beta and beta version has lot of room for improvement.
by Viper
6. October 2009 14:06
Download Demo Projects
This is one of the projects I have been planning to work on for some time. I was looking into building an event notifier in one of
my ASP.Net application. I wanted it to be more like Outlook Web Access (OWA) new email notifier pop-up. It is the one
that slides up from bottom right corner of your browser when there is a new email in your inbox. I had built it in the past
using all javascript solution. Yes, this Microsoft is one of the earliest implementation of so called AJAX applications.
I did not want to deal with all the javascript code related to setting up HTTP calls and then dealing with response and
rendering the results.
I wanted to leverage Silverlight to do all the heavy lifting. And use light weight javascript implementation on client
to do animated sliding and positioning of the popup notifier box. At the end it turned out be quite an elegant solution
that worked on major browsers like Internet Explorer, FireFox and Chrome. This article is an attempt to describe
How to implement OWA style new email notifier popup using Silverlight and Javascript.
The implementation involved the following technologies and I will describe how each component was implemented
- ASP.Net web application
- ASP.Net web service
- Silverlight application
ASP.Net Web Service
Let's start with discussion of the component that is responsible for communication of data between client and server application.
The client requests data from server at certain frequency to check if there are any new messages. So I implemented as simple
ASP.Net web service application with few web methods. For this demo I had a simple method with following signature.
[WebMethod]
public string GetGlobalMessages()
{
List msgs = MockData.GetGlobalMessages();
return msgs.ToJson();
}
For demo application, I implemented a MockData class that creates a random list of messages and then
serializes that collection as JSON and sends it in response. I implemented ToJson as an
extension method on List<StatusMessage> object. You will find it in Extension.cs
file in ActivityData project.
public static string ToJson(this List<StatusMessage> msgs)
{
var ser = new DataContractJsonSerializer(msgs.GetType());
var ms = new MemoryStream();
ser.WriteObject(ms, msgs);
var serializedData = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
return serializedData;
}
You can see there is nothing fancy about this whole implementation to make it work with a Silverlight client. A very
simple ASP.Net web service.
Silverlight Application
This is where all the action happens. There are few components of this application, rendering and data access. Lets us first
discuss data access. The client application is to talk to server at certain frequency. That means I need some kind of
timer going in the application. When this timer ticks at specified interval of time, it send asynchronous request to server
to get new messages. I have implemented this whole mechanism in MessageMonitor application. When
this class is constructed, it creates an instance of DispatchTimer. You may be asking why DispatchTimer and
why not simple Timer application. The problem is that when you are dealing with user interface application, you
can only update the controls on the thread on which they were dispatched. Regular timer does not executes on that dispatcher
thread. So if you will try to update your user interface on that thread you will get exception complaining about
cross threaded access. Here is the code that created DispatcherTimer for my application.
private void CreateMessagePollTimer()
{
_messagePollTimer = new DispatcherTimer();
_messagePollTimer.Tick += new EventHandler(MessagePollTimer_Tick);
_messagePollTimer.Interval = new TimeSpan(0, 0, MessagePollInterval);
}
When the timer ticks it calls MessagePollTimer_Tick method. And that method makes async request to server
to get new messages.
void MessagePollTimer_Tick(object sender, EventArgs e)
{
if (Stopping || MessagePollInProgress) return;
GetMessages();
}
When async request to server completes, the following method gets called. You can see that now it uses the
same JsonSerializer class to de-serialize the response into list of StatusMessage objects. And
then it raises event for objects that have subscribed to the event.
void GetGlobalMessagesCompleted(object sender,
SiteMessagePanel.ActivityDataServices.GetGlobalMessagesCompletedEventArgs e)
{
if (e.Error != null)
{
return;
}
var msgsData = e.Result as String;
var msgs = msgsData.FromJson();
System.Diagnostics.Debug.WriteLine(msgs);
StatusMessageEventArgs args = new StatusMessageEventArgs(msgs);
OnStatusMessageReceieved(args);
}
Page class that implements user interface for popup, handles this event and renders all the
messages.
void Monitor_StatusMessageReceieved(object sender,
ByteBlocks.ActivityData.StatusMessageEventArgs arg)
{
if (arg.Messages.Count == 0)
{
msgTextBlock.Text = "No messages received";
ShowClientPanel(false);
return;
}
msgTextBlock.Text = string.Empty;
messagesPanel.Children.Clear();
foreach (var msg in arg.Messages)
{
StackPanel sp = new StackPanel();
TextBlock tb = new TextBlock();
tb.Text = msg.Title;
tb.TextWrapping = TextWrapping.Wrap;
sp.Children.Add(tb);
messagesPanel.Children.Add(sp);
}
ShowClientPanel(true);
}
ASP.Net application and javascript
ASP.Net application acts as a host for the silverlight control that I created to render messages. I have
implemented a simple Server Control that hosts it. Then I added that control inside a simple
div on the master page. And I have very simple vanilla implementation of the server control. It does
not have very complicated implementation. I simply copied the code generated by silverlight wizard for test page
into that control
<div id="statusslideup">
<ByteBlocks:StatusPanel runat="server" id="statusPanel" />
</div>
Calling Javascript Method From Silverlight
So far we have implemented two pieces of the application that drive the data and render it. Now comes the
fun part. How are we going to trigger the client to show the popup and animate it to come up from bottom.
First, it is Silverlight application that is running the timer. So it is the one that has to trigger the
client. I implemented some java script code that shows the DIV that hosts silverlight client
component. And then small piece of code that implements animation. Silverlight framework
provides a very simple mechanism to invoke any Javascript method that is implemented on client side.
I implemented a very simple method in silvelight application to call my JS method whenever
there are new messages for the user.
private void ShowClientPanel(bool show)
{
HtmlPage.Window.Invoke("_showStatusPanel", show);
}
It could not be any simpler. And the following Javascript function implements
small piece of code that calculates position of popup notifier window based on browser height and
height of element containing silverlight control.
setStatusPanelPosition = function() {
if (_statusdiv) {
_maxPanelPos = document.body.scrollTop + ($(document).height() - _statusdiv.clientHeight);
_curPanelPos = $(document).height();
if (!_isStatusVisible) {
_sliderInterval = setInterval("_slidePanel()", 5);
}
else {
_statusdiv.style.top = _maxPanelPos + "px";
}
_isStatusVisible = true;
}
}
Demo Project
Attached demo project is a collection of Visual Studio 2010 projects and solution. If you do not have VS2010, you
can simply create a new solution and projects in VS2008 and copy the source files in there. You are also
going to need to download Silverlight 3 Toolkit because I use theming controls from that toolkit to give
some zing to the UI.
I hope this demo project helps you in building cooler implementations of OWA like message and event notifier windows.
by Viper
31. July 2009 15:09
Download Demo Project
I have been discussing use of jQuery to send AJAX request to server to get some data every X number of
seconds to get server time and calculate some latency numbers. Now it is time to add some color to it. The numbers that
I am getting is great and provide some useful information. But having a visual of how these numbers are varying with
time will enhance utility of these statistics. So I decided to add some charts to show these latency numbers are
varying with time. In this article I am going to show how you can pass the data obtained from server using AJAX
request to a Silverlight application hosted on the page. This silverlight application uses charting control
from Silverlight toolkit. Lets see how all this fits together to get this to work.
Bridge between Javascript and Silverlight component
In one of earlier posts,
How to setup communication between silverlight applications,
I discussed how you set this bridge up. The sample project for that article was done using Silverlight 2. The mechanism
to set up the communication bridge has not changed in Silverlight 3. So all those concepts still apply for
this project as well. The following code snippets shows declaration of a method decorated with ScriptableMember attribute to
let silverlight framework know that this methos is to be exposed to javascript. And in constructor of the page,
HtmlPage.RegisterScriptableObject method is called to register the class to be exposed to javascript. I do not want to expose
all my properties, fields and methods to javascript. So I have not added scriptable attribute on class itself. I want to control what
is exposed and what is not.
public MainPage()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject("ClockDataClient", this);
SetupChartDisplay();
}
[ScriptableMember]
public void PutNewClockData(string xtx, string data)
{
AddDataPointToPlot(data);
}
This completes what needed to be done from silverlight application to expose its end points to javascript. Now we are going to
see what is done on pages to communicate to silverlight control.
Setting up the page
First thing you need on the page is to include your Silverlight control. On Default.aspx you will find the following
declaration of object tag that will host the control.
<object id="clockDisplayPlugin" data="data:application/x-silverlight-2,"
type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/ClockLatency.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="onLoad" value="onLoadClockDisplay" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="" style="border-style:none"/>
</a>
</object>
All this code was generated by wizard when I added test paste to my project. I added a new param
declaration to handle load event. This event is fired when Silverlight control has been
loaded. On lets see what all javascript is required to send message to silverlight control.
function onLoadClockDisplay(sender, args) {
objClockDisplay = sender.getHost();
}
function sendLatencyData(data) {
if (null != objClockDisplay) {
objClockDisplay.Content.ClockDataClient.PutNewClockData("", data);
}
}
As you can see, in load event handler I saved the reference to Silverlight control object. Then from
my ajax request code, every time I got the data from server, I call sendLatencyData method. This
method calls PutNewClockData method that I exposed from control using ScriptableMember
attribute. This call constitutes of four parts.
objClockDisplay.Content.ClockDataClient.PutNewClockData
objClockDisplay is reference to our silverlight plugin. Content is the property on plugin object through which
control's methods are exposed. ClockDataClient is the key that was used to register the class as scriptable in our control.
PutNewClockData is the name of the method.
Setting up charting control in Silverlight component
I used charting control from Silverlight Toolkit for my project. I decided to use column chart to display latency numbers over time. In
silverlight application project, I added the following XAML on MainPage.
<chartingToolkit:Chart Title="Clock Latency" x:Name="latencyChart" BorderThickness="2">
<chartingToolkit:Chart.Series>
<chartingToolkit:ColumnSeries Title="Latency" DependentValueBinding="{Binding Latency}" AnimationSequence="Simultaneous" />
</chartingToolkit:Chart.Series>
</chartingToolkit:Chart>
In codebehind i created a collection to save data sent from javascript and attached the column series to that collection. I only keep
last 11 entries in the collection.
void SetupChartDisplay()
{
ColumnSeries cs = latencyChart.Series[0] as ColumnSeries;
foreach(var lItem in cs.LegendItems)
{
lItem.Visibility = System.Windows.Visibility.Collapsed;
}
latencyChart.Width = 500;
(latencyChart.Series[0] as DataPointSeries).ItemsSource = DynamicCollectionItemsSource;
}
You can see it was pretty simple to set this whole up and get javascript to send data to silverlight control and
render the charts using those numbers.
Feel free to send any comments or suggestions.
by Viper
30. July 2009 11:41
This morning I was working on a prototype Silverlight application that I developed with Silverlight 2. I copied the project to my new shiny Dell XPS with GTX280 video card. Moment i hit F5 to debug the application, i get the following exception.
Could not load file or assembly 'System.Web.Silverlight' or one of its dependencies. The system cannot find the file specified
Line 2: <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>
It just took me by surprise. I was like, I did not change anything in the project in couple of months and I have new installation of all visual studio tools. After digging through release notes and documentation of Silverlight 3 SDK and tools, i found out that Microsoft has decided to get rid of ASP.Net Silverlight server control that was part of Silverlight 2 SDK. Since I have fresh install of Visual Studio 2008 and tool and I never installed Silverlight 2 SDK on this workstation, I did not have that server control.
Microsoft is recommending to use object tag to insert Silverlight components on the pages now. It is not big deal but it was nice having that server control do all the dirty work behind the scene for you and add object with appropriate parameters and other values. If you still want to continue using that Silverlight server control, you can copy System.Web.Silverlight assembly from other machine or you can install Silverlight 2 SDK.
There seem to be few issues with that ASP.Net server control but none are serious that you could not keep the control and use workaround to get over the issues.
by Viper
19. May 2009 14:37
In silverlight versions prior to 2, we all were setting up navigation for application using work arounds like setting up a layout on a page that will look like a application frame then provide some links etc. on that page to mimic behavior of a navigation system. Well now you do not have to do that any more. Silverlight 3 has included Frame UI element that provides all the navigation facilities. This control is included in System.Windows.Controls.Navigation assembly. You will also notice new namespace System.Windows.Navigation in documentation that provides all the support needed for navigation features.

When you choose to add a new project to IDE, you will notice a new template for adding Silverlight Navigation Application to your solution. The wizard will generate all the necessary XAML and code to include a navigation frame and include three pages as part of the application. This will give you a good starting point to build a navigtion type Silverlight application.

by Viper
19. May 2009 03:44
A long awaited feature for Silverlight, the capability to run silverlight applications without browser. A lot of clients have asked me in the past to build such solutions. They always looked at how Flash application were running on their desktop without it being hosted in browser. Finally Microsoft is delivering that capability in Silverlight 3. It is still in Beta 1 state, but it looks promising already. Here is what microsoft release notes say about this feature.
Out of Browser Capabilities. The new out of browser experience in Silverlight 3 enables users to place their favorite Silverlight applications directly onto their PC and Mac, with links on the desktop and start menu—all without the need to download an additional runtime or browser plug-in. Further, the new experience enables Silverlight applications to work whether the computer is connected to the Internet or not—a radical improvement to the traditional Web experience. Features include:
- Life outside the browser. Silverlight applications can now be installed to and run from the desktop as lightweight web companions. Thus, users can take their favorite Web applications with them, regardless of whether they are connected to the Internet or not.
- Desktop shortcuts and start menu support. Silverlight applications can be stored on any PC or Mac computer’s desktop with links in the start menu and applications folder, and so are available with one-click access.
- Safe and secure. Leveraging the security features of the .NET Framework, Silverlight applications run inside a secure sandbox with persistent isolated storage. These applications have most of the same security restrictions as traditional web apps and so can be trusted without security warnings or prompts, minimizing user interruptions.
- Smooth installation. Because Silverlight applications are stored in a local cache and do not require extra privileges to run, the installation process is quick and efficient.
- Auto-update. Upon launch, Silverlight applications can check for new versions on the server, and automatically update if one is found.
- Internet connectivity detection. Silverlight applications can now detect whether they have Internet connectivity and can react intelligently including caching a users’ data until their connection is restored.
by Viper
17. March 2009 11:53
While adding service reference to a IIS hosted WCF service in Silverlight application, I ran into the following error.
ServiceHost only supports class service Types
In your WCF service if you look at markup .svc file of your service, you will notice from where reference to ServiceHost came. In my service, it looks like as below.
<%@ ServiceHost Language="C#" Debug="true"
Service="SearchService.SearchServer" CodeBehind="SearchServer.svc.cs" %>
You can see that there are only 2 things that can go wrong in this declaration. One, the service class that implements your service does not match with the declaration in this mark up. This is usually the cause of this error because most of the time you modify the wizard generated interface and service class names and you forget to modify the declarations in this SVC file. Make sure that all entries in mark up file match with actual class and interface names.
by Viper
10. March 2009 18:40
When you use Add Service Reference wizard to add a reference to existing WCF service to your silverlight application, you may run into this warning. The description of the warning has all the details about the issue and also tells you what to do to fix it. Now you are wondering why this happened. When you use Visual Studio to create WCF project, you will notice that it generates a configuration file for your service as well where you can configure endpoint, bindings etc. for your WCF service. If you have not modified your configuration file, you may notice something like below set as endpoint.
<endpoint address="" binding="wsHttpBinding"
contract="ByteBlocks.ForExService.ICurrencyService">
Notice that binding is set to wsHttpBinding. This is the binding that provides you connectivity over HTTP/HTTPS with features like reliability, security etc. as specified in WS* protocol. The problem is that Silverlight 2 applications can only connect with ASMX-based web services or services that conform to WS-I Basic Profile 1.1. What that means is that Silverlight applications can only create BasicHttpbinding. So if you modify your service to expose an endpoint that implements basicHttpBinding you are good to go. If your existing WCF service is not tightly coupled with any of WS* features then you can change the existing configuration file as below.
<endpoint address="" binding="basicHttpBinding"
contract="ByteBlocks.ForExService.ICurrencyService">
Now if you try Add Service Reference tool to add reference to your WCF service, you will not see such warning and a nice set of proxy classes will be created for you to start communicating with WCF service.
by Viper
5. March 2009 19:28
While working on a Silverlight project, I had to write and read some data into Isolated storage. While creating a file in a sun folder i kept getting following error.
{System.IO.IsolatedStorage.IsolatedStorageException:
Operation not permitted on IsolatedStorageFileStream.
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor
(String path, FileMode mode, FileAccess access, FileShare share,
Int32 bufferSize, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor
(String path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFile.OpenFile
(String path, FileMode mode, FileAccess access)
at SilverSockets.Page.CreateIsolatedStorageForUser()}
I am developing on Windows7 development machine. So for a moment I thought it may be that there is restriction on Windows7 and I have to make some changes in some silverlight settings or configuration. After spending a few minutes I realized that my creation of sub folder failed in previous step and i did not check it. And I went to on to creating the file in sub folder. Well, the message did not even come close to telling me that folder does not exist. After I fixed creation of sub folder everything worked smoothly. So if you do get this error, check if the folder or file path exists before you go down some wild chase on this error message.
Powered by BlogEngine.NET 1.4.6.1
Theme by Naveen Kohli
|
|