In addition to the ViewDefinition property, which gets or sets the current view as an XML string, the C1OlapPage control also exposes ReadXml and WriteXml methods that allow you to persist views to files and streams. These methods are automatically invoked by the C1OlapPage when you click the “Load” and “Save” buttons in the built-in menu.
These methods allow you to implement predefined views very easily. To do this, start by creating some views and saving each one by pressing the “Save” button. For this sample, we will create five views showing sales by:
Once you have created and saved all the views, create a new XML file called “DefaultViews.xml” with a single “OlapViews” node, then copy and paste all your default views into this document. Next, add an “id” tag to each view and assign each one a unique name. This name will be shown in the user interface (it is not required by C1OlapGrid). Your XML file should look like this:
XAML |
Copy Code
|
---|---|
<OlapViews> <C1OlapPage id="Product vs Country"> <!-- view definition omitted... --> <C1OlapPage id="Employee vs Country"> <!-- view definition omitted... --> <C1OlapPage id="Employee vs Month"> <!-- view definition omitted... --> <C1OlapPage id="Employee vs Weekday">> <!-- view definition omitted... --> <C1OlapPage id="Employee vs Year"> <!-- view definition omitted... --> </OlapViews> |
Now add this file to the project as a resource. To do this, add a new folder to your project and call it “Resources.” Then right-click the Resources folder in the solution explorer, then select the “Add Existing File…” option. Select the XML file and click OK.
Now that the view definitions are ready, we need to expose them in our menu so the user can select them. To do this, copy the following code into the project:
Visual Basic |
Copy Code
|
---|---|
Public Sub New() InitializeComponent() 'no changes here '… ' get predefined views from XML resource Dim views = New Dictionary(Of String, String)() Using s = asm.GetManifestResourceStream("OlapQuickStart.Resources.OlapViews.xml") Using reader = XmlReader.Create(s) ' read predefined view definitions While reader.Read() If reader.NodeType = XmlNodeType.Element AndAlso reader.Name = "C1OlapPage" Then Dim id = reader.GetAttribute("id") Dim def = reader.ReadOuterXml() views(id) = def End If End While End Using End Using ' build new menu with predefined views Dim menuViews = New C1MenuItem() menuViews.Header = "View" menuViews.Icon = GetImage("Resources/views.png") menuViews.VerticalAlignment = VerticalAlignment.Center ToolTipService.SetToolTip(menuViews, "Select a predefined Olap view.") For Each id As var In views.Keys Dim mi = New C1MenuItem() mi.Header = id mi.Tag = views(id) mi.Click += mi_Click menuViews.Items.Add(mi) Next ' add new menu to the page's main menu _c1OlapPage.MainMenu.Items.Insert(6, menuViews) End Sub |
C# |
Copy Code
|
---|---|
public MainPage() { InitializeComponent(); //no changes here //… // get predefined views from XML resource var views = new Dictionary<string, string>(); using (var s = asm.GetManifestResourceStream("OlapQuickStart.Resources.OlapViews.xml")) using (var reader = XmlReader.Create(s)) { // read predefined view definitions while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "C1OlapPage") { var id = reader.GetAttribute("id"); var def = reader.ReadOuterXml(); views[id] = def; } } } // build new menu with predefined views var menuViews = new C1MenuItem(); menuViews.Header = "View"; menuViews.Icon = GetImage("Resources/views.png"); menuViews.VerticalAlignment = VerticalAlignment.Center; ToolTipService.SetToolTip(menuViews, "Select a predefined Olap view."); foreach (var id in views.Keys) { var mi = new C1MenuItem(); mi.Header = id; mi.Tag = views[id]; mi.Click += mi_Click; menuViews.Items.Add(mi); } // add new menu to the page's main menu _c1OlapPage.MainMenu.Items.Insert(6, menuViews); } |
The code loads the XML document with the OLAP definitions, creates a new drop-down menu item using C1Menu, and populates the drop-down with the views found. Each menu item contains the view name in its Header property, and the actual XML node in its Tag property. The node will be used later to apply the view when the user selects it.
Once the drop-down is ready, the code adds it to the C1OlapPage using the MainMenu property. The new button is added after the first several buttons.
There is a simple method called above to load the new menu button’s image, GetImage. Loading a single image does not require this amount of work; however if you load multiple images you will want a nice common method to use time and again.
Visual Basic |
Copy Code
|
---|---|
' utility to load an image from a URI
Private Shared Function GetImage(name As String) As Image
Dim uri = New Uri(name, UriKind.Relative)
Dim img = New Image()
img.Source = New BitmapImage(uri)
img.Stretch = Stretch.None
img.VerticalAlignment = VerticalAlignment.Center
img.HorizontalAlignment = HorizontalAlignment.Center
Return img
End Function
|
C# |
Copy Code
|
---|---|
// utility to load an image from a URI static Image GetImage(string name) { var uri = new Uri(name, UriKind.Relative); var img = new Image(); img.Source = new BitmapImage(uri); img.Stretch = Stretch.None; img.VerticalAlignment = VerticalAlignment.Center; img.HorizontalAlignment = HorizontalAlignment.Center; return img; } |
The only part still missing is the code that will apply the views to the C1OlapPage when the user selects them by clicking the menu item. This is accomplished with the following code:
Visual Basic |
Copy Code
|
---|---|
' apply a predefined view
Private Sub mi_Click(sender As Object, e As SourcedEventArgs)
Dim mi = TryCast(sender, C1MenuItem)
Dim viewDef = TryCast(mi.Tag, String)
_c1OlapPage.ViewDefinition = viewDef
End Sub
|
C# |
Copy Code
|
---|---|
// apply a predefined view void mi_Click(object sender, SourcedEventArgs e) { var mi = sender as C1MenuItem; var viewDef = mi.Tag as string; _c1OlapPage.ViewDefinition = viewDef; } |
The code retrieves the OLAP definition as an XML string by reading the menu’s Tag property, then assigns it to the C1OlapPage.ViewDefinition property.
If you need further customization, you can also choose not to use the C1OlapPage at all, and build your interface using the lower-level C1OlapPanel, C1OlapGrid, and C1OlapChart controls. The source code for the C1OlapPage control is included with the package and can be used as a starting point. The example in the “Building a custom User Interface” section shows how this is done.