PivotViewer and MVVM
PivotViewer series
- Building your first PivotViewer application
- Runtime PivotViewer collection creation
- PivotViewer – Working with Facets
- Handling PivotViewer events
- PivotViewer – Custom actions
- PivotViewer and MVVM
Intro
The MVVM patterns is a commonly used pattern in Silverlight. Because of databinding MVVM suits perfectly for WPF and Silverlight. But use it only if appropriate. Often the pattern is used when it isn’t necessary. The usage of any pattern should be a helping tool, not an enforced law. Having that of my chest, lets look at the Silverlight PivotViewer control in combination with the MVVM pattern.
To make a long story short, the PivotViewer control isn’t suitable for use in MVVM out of the box. But there are a few ways you can make it work.
Wrapping the PivotViewer in a UserControl
The most simple way to get the control to work in an MVVM application is to place the control in a UserControl. You can use this control in your View and bind to properties you add to the UserControl. You’ll have to add dependency properties to the UserControl for each property you want to data bind to. The downside of wrapping the PivotViewer control in a UserControl is that you will have to add code to the CodeBehind of the UserControl.
For example a URL where the .CXML file is located. If this value changed you would like to load the collection. In the current version of the PivotViewer the only way to do this is to call the LoadCollection method on the PivotViewer control. By adding a dependency property to the UserControl you can bind a property of the ViewModel to this and have it load a collection on changes.
This dependency property with its “OnChange” method might look something like this:
public string UrlSource{
get { return (string)GetValue(UrlSourceProperty); }
set { SetValue(UrlSourceProperty, value); }
}
public static readonly DependencyProperty UrlSourceProperty =
DependencyProperty.Register("UrlSource",
typeof(string),
typeof(PivotViewerUserControl),
new PropertyMetadata(string.Empty,
OnUrlSourceChanged));
private static void OnUrlSourceChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(d))
{
var userControl = (PivotViewerUserControl) d;
userControl.Pivot.LoadCollection((string) e.NewValue,
string.Empty);
}
}
A logical next step would be to add a dependency property for the ViewerState parameter of the LoadCollection method and call it only when both are set or if the UserControl is Loaded.
To get notified when the selected item changed you can use an ICommand. Add a dependency property of type ICommand to the UserControl to be able to bind an implementation of the ICommand from the ViewModel to it. The property changed event on the PivotViewer control is handled. When the “CurrentItemId” property changes, thus the selected item changes, the event is executed. As a small extra feature the item is looked up on the PivotViewer and the whole PivotItem is passed as a parameter to the execute method.
public PivotViewerUserControl()
{
InitializeComponent();
Pivot.PropertyChanged += Pivot_PropertyChanged;
}
public ICommand SelectedItemChangedCommand
{
get { return (ICommand)GetValue(SelectedItemChangedCommandProperty); }
set { SetValue(SelectedItemChangedCommandProperty, value); }
}
public static readonly DependencyProperty SelectedItemChangedCommandProperty =
DependencyProperty.Register("SelectedItemChangedCommand",
typeof(ICommand),
typeof(PivotViewerUserControl),
new PropertyMetadata(null));
private void Pivot_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "CurrentItemId")
{
if (this.Pivot.CurrentItemId == null)
{
// deselection
this.SelectedItemChangedCommand.Execute(null);
}
else
{
// selection
PivotItem item = Pivot.GetItem(Pivot.CurrentItemId);
this.SelectedItemChangedCommand.Execute(item);
}
}
}
Extending the PivotViewer control itself
Another way to get to PivotViewer to work in an MVVM application is to extend the PivotViewer itself. The dependency properties you’ll be adding to the control are pretty much the same as the ones shown in the previous section, with the extend that you have better access to the guts of the PivotViewer control. This way you have access to the Custom Actions for example.
Where to go next
You could start by implementing all properties of the PivotViewer control as dependency properties and add a ICommands to event handlers. Maybe you can find constructions where you can extend the control with your own needs
I just hope that in the next version of the PivotViewer Microsoft did this boring work for us so we don’t have to.
I don’t have plans for a next tutorial on the PivotViewer, yet. If you have question or requests just let me know and I’ll see if I can help you. If you want to be the first to when a new tutorial is available, you can subscribe to the RSS-Feed or follow me on twitter.
SilverBullet #13 – System.Threading.SynchronizationContext
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
When writing the demo for the code-camp I ran into issues getting back on the UI thread after calling a webservice. The call to the webservice was made from the UI thread, but the callback was made on a different thread. The System.Threading.SynchronizationContext class held the solution.
The System.Threading.SynchronizationContext class is a base class that provides a thread-free context. It contains a read-only static property named Current, which gets the thread from which it is requested. When the current context is kept while the asynchronous call to a webservice is made, it can be used the call method in that context. The SynchronizationContext.Post can do this asynchronous, the SynchronizationContext.Send can do this synchronous.
Sample
Let me try to explain with a small sample which is taken from the code-camp demo.
The GetSearch(string searchText) method is called, which begins the call to the Bing API.
public class BingModel : IBingModel
{
// this string is used to make the actual call to the bing API.
// the blancs are filled in when SearchBing method is called
const string BingRequestURL =
"http://api.bing.net/json.aspx?AppId={0}&Version=2.2&"
+"Market=en-US&Query={1}&Sources=web&Web.Count={2}";
// the request is kept so it can be used to handle the response
private WebRequest request;
// the SearchBing method is called from the UI thread
//(note: //you can get your AppId at http://bing.com/developers)
public void SearchBing(string searchText, string appId)
{
//the blancs are filled in
string requestString =
string.Format(BingRequestURL,
appId,
HttpUtility.UrlEncode(searchText),
20); //20 results will be givin.
//a new request is made.
request = HttpWebRequest.Create(requestString);
//the getting of the response is started. The OnRequestCompleted
//method is provided so it can be called when the request is
//completed. The Current SynchronizationContext is provided as
state so it can be handled by the result.
request.BeginGetResponse(OnRequestCompleted,
SynchronizationContext.Current);
}
//when the request is completed this method is called
private void OnRequestCompleted(IAsyncResult ar)
{
//the response is extracted from the result and read thru a stream.
var webResponse = (HttpWebResponse)request.EndGetResponse(ar);
var response = new StreamReader(webResponse.GetResponseStream());
//Because a string of Json is returned by the service, this string is
//parsed into a JsonObject.
var json = JsonObject.Parse(response.ReadToEnd());
//the ExtractResults method (defined below) is used to create
//an enumeration of the results
IEnumerable<BingResult> ress = ExtractRestults(json);
// this method (defined below) is used to fire a custom event on the UI thread
// the state is provided as Synchronization context along with the json results
InvokeSearchBingCompletedEvent(ar.AsyncState as SynchronizationContext, ress);
}
private void InvokeSearchBingCompletedEvent(SynchronizationContext context,
IEnumerable<BingResult> ress)
{
if (context != null) // just in case the context has become null somehow
// call an anonymous method asynchronous on the context that was used to start
//the search
context.Post((e) =>
{
if (SearchBingCompleted != null)
//raise the event
SearchBingCompleted(this, new SearchBingCompletedArgs()
{
SearchResults = ress.ToList()
}
);
}, null);
}
// Extract search result from Json returned by Bing API
private static IEnumerable<BingResult> ExtractRestults(JsonValue json)
{
var results = json["SearchResponse"]["Web"]["Results"] as JsonArray;
return from res in results
select new BingResult()
{
Title = res["Title"],
Url = res["Url"]
};
}
// the definition of the event handler
public event EventHandler<SearchBingCompletedArgs> SearchBingCompleted;
}
SilverBullet #12 – System.Windows.Browser.HttpUtility
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
This time I would like a little helper class to your attention. When working in a web environment ever so often you need to encode/decode a Url or a piece of Html. In Silverlight you need to look for the System.Windows.Browser.HttpUtility class. The static System.Windows.Browser.HttpUtility class contains 4 static methods. A set for encoding and decoding Html and a set for encoding and decoding URLs.
The HttpUtility.HtmlEncode method converts all special Html characters to their encoded versions. Because html can’t display its control characters directly, they have to be converted to be displayed. An < character will be interpreted by Html as the start of an Html tag. To display it, it has to be encoded.
For example:
< is encoded into <
> is encoded into >
& is encoded into &
The counterpart of the HttpUtility.HtmlEncode method is the HttpUtility.HtmlDecode method. This method converts all encoded characters back to normal character.
When sending strings to urls, a lot of characters will cause misinterpretation on the receiving end. To replace this characters by their hexadecimal escape equivalents in a string you can use the HttpUtility.UrlEncode method. For example, an empty space is likely to cause trouble. After encode a string with a space, the space is replaced by %20.
To reverse the process and change the hexadecimal escape characters back to their normal form, you can use the HttpUtility.UrlDecode method.
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #10 System.Windows.Documents.Run
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
When showing text to a user it’s often necessary to show a few words in Italic or Bold. To do this, use the System.Windows.Documents.Run class. This class provides a small bit of HTML – like features inside a Silverlight TextBlock. But, instead of using HTML tags you have to use the Run class.
The Run class inherits from the abstract System.Windows.Documents.Inline which provides most of the properties to use. A few of the most common are:
- FontWeight – sets the weight of the text, it’s Boldness, and can be of any of the static properties in FontWeights.
- FontStyle – is used to show the text in Italic. The only possibilities are Normal or Italic as provided by FontStyles.
- Foreground – sets the brush for the color of the text. This can be used as any other brush in Silverlight, like an LinearGradientBrush or an ImageBrush
There are couple more properties which you can find here.
Another thing that might become useful when using the Run class to simulate a bit of HTML like behavior is the System.Windows.Documents.LineBreak class. This class does not have any properties or methods and can be compared to the <br /> tag in HTML.
Here’s a small example to show how the Run class is used in xaml:
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock TextWrapping="Wrap" FontFamily="Verdana">
This is an example with
<Run FontWeight="Black">Bold</Run>,
<Run FontStyle="Italic">Italic</Run> and
<Run Foreground="red">Colored</Run>
text...<LineBreak />
It's even possible to use<LineBreak />
multiple <LineBreak />lines of text.
</TextBlock>
</Grid>
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #9 – System.Windows.Analytics
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
When developing applications, especially graphic intensive web applications you want to monitor the performance when running. The System.Windows.Analytics class can help you with that.
The class has no methods of any significance and only three read-only properties:
- AverageProcessLoad – shows the average of all cores on how much of the CPU the process is using
- AverageProcessorLoad – shows the amount of CPU processing that’s being used
- GpuCollection – holds a collection of GpuInformation objects. The GpuInformation class contains information about the GPU. Every element in the collection has three properties: DeviceId, DriverVersion and VendorId.
Using these properties is very simple as this example will show:
This example uses a timer to display and update the values from the properties in the System.Windows.Analytics class.
To display the various values added a couple of text boxes and a listbox to stackpanel. Too keep things simple for this example, just add the stackpanel to MainPage.xaml in a new silverlight project.
<StackPanel x:Name="LayoutRoot" Orientation="Vertical">
<TextBlock x:Name="AverageProcessLoad" />
<TextBlock x:Name="AverageProcessorLoad" />
<ListBox x:Name="GpuInfo" />
<TextBlock x:Name="Time"/>
</StackPanel>
Next, add the following to the codebehind, MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
var t = new DispatcherTimer();
t.Tick += TickHandler;
t.Interval = new TimeSpan(0,0,1);
t.Start();
}
void TickHandler(object sender, EventArgs e)
{
Time.Text = DateTime.Now.ToLongDateString()+ " -- "+
DateTime.Now.ToLongTimeString();
var an = new Analytics();
AverageProcessLoad.Text =
an.AverageProcessLoad.ToString();
AverageProcessorLoad.Text =
an.AverageProcessorLoad.ToString();
GpuInfo.Items.Clear();
foreach (var gpuInformation in an.GpuCollection)
{
GpuInfo.Items.Add(string.Format(
"ID:{0}, Version:{1}, vendorId{2} ",
gpuInformation.DeviceId,
gpuInformation.DriverVersion,
gpuInformation.VendorId)
);
}
}
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #8 – Accessing local files
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
Although the Silverlight security model prevents access to the local file system, it is very easy to open and save or import and export files to and from the file system. It is not possible to gain any information about the local file system, but the Silverlight framework can give you a stream to a file. Access is only granted if the dialogs are used from user-initiated code, like the Click event for example. If you try to show the dialog from other code, a SecurityException is thrown.
Opening a file uses the OpenFileDialog class, which lives in the System.Windows.Controls namespace. The OpenFileDialog class provides only one method, ShowDialog. This method shows a dialog that is modal to the browser, which means your application is locked for user input for as long as the dialog window is open. The method returns a bool indicating if one or more files are selected or not.
The OpenFileDialog class has a few properties:
- Filter – a string to get or set the filter on which files are shown, for example “Excel (.xls)|*.xls|All Files (*.*)|*.*”
- FilterIndex – an integer to get or set the index for the filter dropdown list
- Multiselect – a bool to enable or disable the selection of multiple files
- File – gets a FileInfo object for the selected file. If multiple files are selected, this is the first
- Files – gets a collection of FileInfo objects that represents all selected files
Saving a file is pretty similar. Saving uses the SaveFileDialog class, which can be found in the System.Windows.Controls namespace too. Showing the dialog is done the same way as opening a file, using the ShowDialog method. When the user has selected a file or filename to save to, you can use the OpenFile method to get a stream to write the contents to. You should only call this method if showing the dialog returns True. If no file is selected when trying to open it, an InvalidOperationException is thrown.
The SaveFileDialog class has only four properties:
- DefaultExt – a string to get or set the default extension
- SafeFileName – a string to get the filename for the selected file
- Filter – a string to get or set the filter on which files are shown
- FilterIndex – an integer to get or set the index for the filter dropdown list
There’s an example demonstrating the OpenFileDialog class on MSDN, which shows a number of properties in practice. The example can be found here.
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #7 – System.Windows.Messaging
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
Most often Silverlight applications take up the whole screen and the page that is hosting the application contains only one control. It is possible to split you application into smaller controls. This can be valuable when you are using silverlight 3 in SharePoint parts, or just to leverage your webpage with a few nice looking controls. It’s even possible to take this a whole mile further. Joe Stegman gave an awesome demonstration of this at the Mix09 event earlier this year. Silverlight 3 controls can communicate over the boundaries of tabs inside a browser, and even over the boundaries of the browsers itself. Sending messages back and forth between IE, Firefox, Chrome and even Out-Of-Browser. To get this all to work you have to take a look at the System.Windows.Messaging namespace.
The namespace contains only a few classes of which these two are the most important:
It is not hard to guess what these do, the first one sends messages and the second one receives them. Both classes are not hard to understand. Let me explain with a bit of code.
Sending Messages:
public void someMethod()
{
LocalMessageSender myMessageSender =
new LocalMessageSender("myReceiverName");
myMessageSender.SendCompleted += myMessageSenderSendCompleted;
myMessageSender.SendAsync("a message from control 1");
}
void myMessageSenderSendCompleted(object sender, SendCompletedEventArgs e)
{
Console.WriteLine("Send to " + e.ReceiverName + "->" + e.Message);
}
When the someMethod() method is called, a new LocalMessageSender object is created. The parameter “myReceiverName” is the identifier for the communication between the Silverlight controls.
After sending a message, the SendComplete event is fired. In this example it is handled my the myMessageSenderSendCompleted event handler and a string containing the message and the receiver name are written to the console.
Then SendASync method sends a message.The message can only be a string, but may take up to 1 Mb in size.
Receiving messages is as easy as sending them:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
LocalMessageReceiver myMessageReceiver;
myMessageReceiver = new LocalMessageReceiver("myReceiverName");
myMessageReceiver.MessageReceived += myMessageReceiverMessageReceived;
myMessageReceiver.Listen();
}
void myMessageReceiverMessageReceived(object sender,
MessageReceivedEventArgs e)
{
Console.WriteLine("Received from " + e.ReceiverName + "->" + e.Message);
}
In the Loaded event handler of a UserControl a new instance of a LocalMessageReceiver is created. It is given the same string as a parameter as the Sender in the earlier example, “myReceiverName”.
When a message is received, the MessageReceived event is raised, in this example it is handled my the myMessageReceiverMessageReceived event handler, which writes the message it received and the name of the receiver to the console.
The last method, Listen(), starts the listener. From now on messages can be received.
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #6 – System.Windows.EventTrigger
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
There are situations when you would like to start an animation as soon as your application is loaded. The EventTrigger class is what you need in that case. You may know this class from WPF, but the Silverlight version is very limited. The nice thing about this class is that it can be used in xaml, so you don’t have to do anything in codebehind.
The EventTrigger class has a couple of uninteresting properties and methods inherited from DependencyObject. The class has only 1 property you would actually use directly when defining it in Xaml: RoutedEvent. This is the event that will trigger the animation. At this point, only the Loaded event is supported. But often this is what you need anyway.
The animation you want to start is placed inside the EventTrigger element and inside a BeginStoryBoard element. The EventTrigger can contain multiple BeginStoryBoards. Each BeginStoryBoard can contain only one storyboard.
In case you want to look at the storyboards from code, the BeginStoryBoard objects are stored in a TriggerActionCollection in the Actions property of the EventTrigger.
Here’s a very simple example of an animation being played when the application is loaded:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<UserControl.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard SpeedRatio="0.01">
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].
(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:02" Value="300"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid x:Name="LayoutRoot" Background="White">
<Ellipse x:Name="ellipse" Fill="#FFFF0000" Stroke="#FF000000"
Height="60" Width="60"
HorizontalAlignment="Left"
VerticalAlignment="Top" >
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
</UserControl>
|
Tags van Technorati: Silverlight
|
![]() |
|
|
SilverBullet #5 – System.Windows.ApplicationServiceContext
I’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.
When running Silverlight outside the browser, there’s the possibility that the computer that is running the applications is disconnected. This is where the System.Windows.ApplicationServiceContext class comes in. This class represents the initial state when the application is started. It has no methods of any significance, only two read only properties.
- ApplicationInitParams : Gets the parameters specified by the page where the silverlight plug-in is embedded in.
- RunningOffline: Indicated if the application is running in offline mode
The ApplicationInitParams property is a Dictionary of a string/string key/value pair and contains parameters with their values. On MSDN is a detailed article about how to define the HTML for using init parameters and query parameters and how to read them in Silverlight.
The RunningOffline property is a bool. It is True if the application is running offline and False when the application is running online. If you have enabled you application to run out of the browser, you can check this property to see if you can access any online services which may not be available when running offline.
|
Tags van Technorati: Silverlight
|
|
|
|


