With the release of Silverlight 5 just around the corner, I thought I would start a series on the new PivotViewer and how to get up and running with it. We will start the series off by exploring how to create a client side collection.
One of the most anticipated features of the new PivotViewer is the ability to create client-side collections. PivotViewer accomplishes this by utilizing the traditional ItemsSource property for data and a form of XAML data templates to define the trading card. It is interesting to note that the fundamental core of PivotViewer is still using the DeepZoom technology. If you are thinking that DeepZoom only handles images and not XAML, you would be correct. Under the hood, PivotViewer is rendering the data templates to images and then adding those images to DeepZoom. Remembering that little tidbit will help later down the road.
The Basics
First things first, let’s get a PivotViewer control into our application. One of the great changes in the PivotViewer is that instead of 4 libraries we are down to one. So to include the PivotViewer in your application, you simple need to add a reference to System.Windows.Controls.Pivot.
Now we can add a PivotViewer to our application like this:
<Grid x:Name="LayoutRoot" Background="White">
<pivot:PivotViewer x:Name="pViewer"/>
</Grid>
Doesn’t get much simpler than that, now does it?
Getting your Data
In order to focus in our demo, we are going to generate some dummy data on the client. Of course, you are most likely going to be pulling in more meaningful data (let’s hope anyway) and you can still do that in the traditional ways.
public class DemoItem : INotifyPropertyChanged
{
public string ShortName { get; set; }
private string _color;
public string Color
{
get { return _color; }
set
{
_color = value;
NotifyProperty("Color");
}
}
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
NotifyProperty("Value");
}
}
private string _data1;
public string Data1
{
get { return _data1; }
set
{
_data1 = value;
NotifyProperty("Data1");
}
}
private DateTime _stamp;
public DateTime Stamp
{
get { return _stamp; }
set
{
_stamp = value;
NotifyProperty("Stamp");
}
}
public static ObservableCollection<DemoItem> BuildData()
{
var data = new ObservableCollection<DemoItem>();
for (int i = 0; i < 100; i++)
{
var itm = new DemoItem()
{ ShortName = i.ToString("000") };
var mod = i % 3;
switch (mod)
{
case 0:
itm.Color = "Blue";
break;
case 1:
itm.Color = "Red";
break;
case 2:
itm.Color = "Green";
break;
}
itm.Data1 = i % 2 == 0 ? "Even" : "Odd";
itm.Stamp = DateTime.Now.AddDays(-1*i);
data.Add(itm);
}
return data;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyProperty(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this,
new PropertyChangedEventArgs(propName));
}
#endregion
}
As you can see there isn’t a whole lot going on here. The BuildData() method knocks out some data that will let us see PivotViewer in action. I used a string for the color property so it would map to a PivotViewer property cleanly.
Now that we can generate our data, how do we get it into PivotViewer? It’s as simple as using the ItemsSource property (yep just like a normal Silverlight control).
pViewer.ItemsSource = DemoItem.BuildData();
Setting up your PivotProperties
In the original PivotViewer properties were defined as facets. In the new version we now have PivotProperties. There hasn’t been any changes to the number or types of properties. The four available types are :
1. PivotViewerStringProperty
2. PivotViewerNumericProperty
3. PivotViewerDateTimeProperty
4. PivotViewerLinkProperty
PivotViewer has a PivotProperties property (try saying that 3 times fast) that you can set via code or in XAML. For completeness sake, let’s take a look how each would look. Both of these examples yield the same result.
PivotViewer Properties in XAML:
<pivot:PivotViewer x:Name="pViewer">
<pivot:PivotViewer.PivotProperties>
<pivot:PivotViewerNumericProperty
Id="Value"
Options="None"
Binding="{Binding Value}"/>
<pivot:PivotViewerStringProperty
Id="Data1"
Options="CanFilter,CanSearchText"
Binding="{Binding Data1}"/>
<pivot:PivotViewerStringProperty
Id="Color"
Options="CanFilter,CanSearchText"
Binding="{Binding Color}"/>
<pivot:PivotViewerDateTimeProperty
Id="Stamp"
Options="CanFilter"
Binding="{Binding Stamp}"/>
</pivot:PivotViewer.PivotProperties>
</pivot:PivotViewer>
PivotViewer Properties in code behind:
pViewer.PivotProperties = new List<PivotViewerProperty>()
{
new PivotViewerNumericProperty()
{
Binding = new Binding("Value"),
Id = "Value",
Options = PivotViewerPropertyOptions.None
},
new PivotViewerStringProperty()
{
Binding = new Binding("Data1"),
Id = "Data1",
Options = PivotViewerPropertyOptions.CanFilter
| PivotViewerPropertyOptions.CanSearchText
},
new PivotViewerStringProperty()
{
Binding = new Binding("Color"),
Id = "Color",
Options = PivotViewerPropertyOptions.CanFilter
| PivotViewerPropertyOptions.CanSearchText
},
new PivotViewerDateTimeProperty()
{
Binding = new Binding("Stamp"),
Id = "Stamp",
Options = PivotViewerPropertyOptions.CanFilter
}
};
There are only a few options for a PivotProperty, so I thought it would be worth listing them. Here is a break down of each property and how it effects how the PivotProperty is used inside of PivotViewer
PivotProperty Options
None
|
No options are set
|
Private
|
If set, it will not display property in detail pane
|
CanFilter
|
Shows the property in the filter pane and the sort drop down box
|
CanSearchText
|
The search box will search for this property for matches
|
Wrapping Text
|
Will wrap the text within the detail pane
|
Trading Cards
Now we have our data and have mapped the data to the a collection of PivotProperties, what’s next? The last set it to define what the trading card is going to look like. For this post we are going to look at a basic solution which we will expand upon in the next post.
XAML data templates in PivotViewer take the shape of a PivotViewerItemTemplate. PivotViewer has a ItemTemplates property that is used to map one or more templates for your trading cards. For our case we are going to create a simple trading card that consists of a Border that is filled with the card’s Color property and put a ShortName property in the middle of the Border. The template will look something like this:
<pivot:PivotViewerItemTemplate x:Key="DemoTemplate">
<Border Width="300" Height="300"
Background="{Binding Color,
Converter={StaticResource colorConverter}}">
<TextBlock Text="{Binding ShortName}" FontSize="20"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</pivot:PivotViewerItemTemplate>
You might notice that I added a value converter to the background. Since we are storing the color as a string, we need to map it to a SolidColorBrush. SL doesn’t expose all of the Color methods you find in .NET, so we have to be a bit clever in getting the color mapped. Here is the value converter that I am using:
public class TextToSolidColorConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
var xaml = "<SolidColorBrush " +
"xmlns='http://schemas.microsoft.com/client/2007' " +
"Color=\"" + value.ToString() + "\"/>";
return XamlReader.Load(xaml);
}
public object ConvertBack(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
With our template added as a resource, we can set the template in code with the following:
pViewer.ItemTemplates = new PivotViewerItemTemplateCollection()
{
(PivotViewerItemTemplate) Resources["DemoTemplate"]
};
And that is really all there is to it. If we run our solution, we should get something like this: