RSS

CustomActions (ItemAdorners) in PivotViewer v2

28 Oct

You can download the example solution here.

PivotViewer v1 introduced the concept of CustomActions on tiles. Enabling the behaviour was a 3-stage process. Firstly, you had to implement your own PivotViewer control and override the GetCustomActionsForItem method. Secondly, you had to write some CustomAction-derived classes. Thirdly, you had to handle the ItemActionExecuted event that the PivotViewer control raised in order to evaluate which CustomAction had been executed. This was not an ideal approach.

PivotViewer v2 has a much richer framework for adding custom functionality to your tiles. I’ll cover some advanced techniques in my next post but, for now, I’ll show you how CustomActions have evolved in this version.

The new version also takes a 3-stage approach, but it’s a lot less invasive of the PivotViewer control. For one, you dont’t have to implement your own custom class any more.

Step 1: Creating the ItemAdorner Style

The new PivotViewer control allows us to define a style for the CustomActions; now called ItemAdorners. This is just a standard Silverlight style, but the trick is to include a PivotViewerDefaultItemAdorner control.

<p:PivotViewer.ItemAdornerStyle>
  <Style TargetType="p:PivotViewerItemAdorner">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="p:PivotViewerItemAdorner">
          <p:PivotViewerDefaultItemAdorner 
            IsTabStop="False"
            DataContext="{TemplateBinding Content}"
            CommandsRequested="GetCommands"
            IsItemSelected="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsItemSelected}" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</p:PivotViewer.ItemAdornerStyle>

Notice how we’ve bound the IsItemSelected property. This allows the control to hide itself when the tile doesn’t have focus. Later, we’ll be wiring up the GetCommands event but first we have to create some commands.

Stage 2: Creating Commands

Any command associated with the adorner must implement a new interface IPivotViewerUICommand. This extends the, now familiar, ICommand interface and retains some familiar members from CustomActions in v1…

using System;
using System.Windows.Input;

namespace System.Windows.Controls.Pivot
{
    public interface IPivotViewerUICommand : ICommand
    {
        string DisplayName { get; }
        Uri Icon { get; }
        object ToolTip { get; }
    }
}

So, let’s create a simple Hello World command. We’ll pass in a reference to the underlying item that is the data source of our tile so that the command has access to its caller…

public class HelloWorldCommand : IPivotViewerUICommand
{
  private readonly Person _person;

  public HelloWorldCommand(Person person)
  {
    _person = person;
  }

  public string DisplayName
  {
    get { return "Hello World"; }
  }

  public Uri Icon
  {
    get { return new Uri("http://dev.opera.com/articles/view/opera-extensions-hello-world/hello.png"); }
  }

  public object ToolTip
  {
    get { return "Click this to say hello"; }
  }

  public bool CanExecute(object parameter)
  {
    return true;
  }

  public event EventHandler CanExecuteChanged;

  public void Execute(object parameter)
  {
    MessageBox.Show(_person.Name + " says 'Hello'");
  }
}

Stage 3: Connecting the Commands

Lastly we’ll add a handler for the PivotViewerItemAdorner’s GetCommands event where we’ll instantiate and add the commands…

public partial class MainPage : UserControl
{
  private void GetCommands(object sender, PivotViewerCommandsRequestedEventArgs e)
  {
    e.Commands.Add(new HelloWorldCommand(e.Item as Person));
  }
}

This is the result:

In my next post I’ll show you how you can get creative with ItemAdorners in ways that weren’t possible in v1.

You can download the example solution here.

Advertisements
 
25 Comments

Posted by on October 28, 2011 in PivotViewer

 

Tags: , , , , , , ,

25 responses to “CustomActions (ItemAdorners) in PivotViewer v2

  1. Kirikamal

    October 31, 2011 at 4:26 am

    Thank you very much!!!!

    I’m looking this……

    – Kirikamal

     
  2. RM in LA

    November 21, 2011 at 4:25 am

    Great post and code sample as usual. Eagerly looking forward to the follow-up post you mentioned above

    Any ETA? 🙂

     
  3. Kirikamal

    December 21, 2011 at 3:41 am

    Hi,

    Recently I’ve updated to Final release of Silverlight. Now got problem.

    When compile it gives an error

    “Property ‘Content’ was not found in type ‘PivotViewerItemAdorner”

    Do you know why?

    – Kirikamal

     
  4. goodcoffeegoodcode

    December 21, 2011 at 8:53 am

    Hi Kirikamal,

    Yeh, there were some breaking changes in the RTM. I even found one with basic data binding. Happy to help, can you post an example of the xaml please?

    Chris

     
    • Kirikamal

      December 21, 2011 at 8:57 am

      Hi,

      I solved the problem by removing the DataContext.

      Following is my xaml code:

      And I’ve removed “DataContext=”{TemplateBinding Content}” line. It works.

      Thank you.

      – Kirikamal

       
    • Kirikamal

      December 21, 2011 at 8:59 am

      Opps forgot to paste the code:

      – Kirikamal

       
  5. Kruddler

    January 12, 2012 at 11:19 pm

    The download sample link down’t work, it just refreshes the page. Could you please fix the link?

     
    • goodcoffeegoodcode

      January 13, 2012 at 5:55 am

      Hi Christian,

      I’ve just checked both links and they work. Have you tried right clicking and choosing ‘Save As…’?

      Thanks,

      Chris

       
  6. Kruddler

    January 16, 2012 at 2:47 am

    Sorry, there must have been something wrong with my internet connection. Eventually I was able to download the solution. However, when I tried to run the sample, I just get:

    Error HRESULT E_FAIL has been returned from a call to a COM component.

    I am using version 5 of Silverlight. It turns out that the line below was casuing the problem.

    DataContext=”{TemplateBinding Content}”

    It should be:

    DataContext=”{Binding}”

     
  7. David T

    March 13, 2012 at 3:59 pm

    Say I want the adorner to be able to link to a website and have it pull that link up on a new page, how would I be able to read from my CXML and grab the link of the website in the CXML and also tie it to the item?

    Is it possible?

     
  8. Paul

    April 22, 2012 at 9:33 pm

    Hi, can you tell me how I would put your code below in a MVVM viewmodel

    private void GetCommands(object sender, PivotViewerCommandsRequestedEventArgs e)
    {
    e.Commands.Add(new HelloWorldCommand(e.Item as Person));
    }

    Thanks

    pqsik

     
    • Masaab

      June 3, 2012 at 1:03 pm

      Any Solution for the CommandsRequested implementation in MVVM

       
  9. paul

    April 23, 2012 at 8:36 pm

    Hi, I posted this the other day but I cannot see it, so I post it again. Sorry if it show twice.

    I would like to move this into a MVVM viewmodel property and need help

    CommandsRequested=”{Binding Path=ViewModelProperty}”

    private void GetCommands(object sender, PivotViewerCommandsRequestedEventArgs e)
    {
    e.Commands.Add(new HelloWorldCommand(e.Item as Person));
    }

    Thanks
    pqsik

     
    • Masaab

      June 3, 2012 at 1:01 pm

      DID Got any Solution for the CommandsRequested implementation in MVVM

       
  10. johntomaselli

    May 11, 2012 at 4:09 pm

    Hi,
    In following this post along with the Add,Remove and Change Cxml, I was able to accomplish a large part of the required task of selecting individual items and later exporting the list. In all my cases below I’d like to know to get the values displayed in the info panel.
    TIA
    John

    1) I first tried adding a simple button above the pivotviewer with the idea of extracting the data values displayed in the the info panel of the selected item.
    private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
    {

    if (Viewer.SelectedIndex >= 0)
    MessageBox.Show(_data[Viewer.SelectedIndex].GetPropertyValue(“Profession”).ToString()+ ” “+ _data[Viewer.SelectedIndex].GetPivotPropertyById(“Profession”).Id.ToString()) ;

    2) Iterate through all items in the collection
    var Allitems = Viewer.ItemsSource
    as ObservableCollection;
    foreach (PivotViewerItem item in _data)
    {

    MessageBox.Show(string.Format(“Show details by getting the 15 items of info panel of {0}”, item.Id));// Name));
    }

    3) Have a way to pass the data as in your HelloWorldCommand
    public HelloWorldCommand(ObservableCollection _data, System.Windows.Controls.ListBox listbox)

     
  11. johntomaselli

    May 11, 2012 at 7:29 pm

    Hi,
    I finally figured out how to get a value!
    if (Viewer.SelectedIndex >= 0)
    {
    PivotViewerItem item = _data[Viewer.SelectedIndex];
    string itm = item.GetPropertyValue(“Profession”)[0].ToString();
    MessageBox.Show(itm);
    }

     
  12. johntomaselli

    May 11, 2012 at 7:31 pm

    Hi,
    In following this post along with the Add,Remove and Change Cxml, I was able to accomplish a large part of the required task of selecting individual items and later exporting the list. In all my cases below I’d like to know to get the values displayed in the info panel.
    TIA
    John

    1) I first tried adding a simple button above the pivotviewer with the idea of extracting the data values displayed in the the info panel of the selected item.
    private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
    {

    if (Viewer.SelectedIndex >= 0)
    MessageBox.Show(_data[Viewer.SelectedIndex].GetPropertyValue(“Profession”).ToString()+ ” “+ _data[Viewer.SelectedIndex].GetPivotPropertyById(“Profession”).Id.ToString()) ;

    2) Iterate through all items in the collection
    var Allitems = Viewer.ItemsSource
    as ObservableCollection;
    foreach (PivotViewerItem item in _data)
    {

    MessageBox.Show(string.Format(“Show details by getting the 15 items of info panel of {0}”, item.Id));
    }

    3) Have a way to pass the data as in your HelloWorldCommand
    public HelloWorldCommand(ObservableCollection _data, System.Windows.Controls.ListBox listbox)

     
  13. johntomaselli

    May 11, 2012 at 8:42 pm

    Hi,
    Thanks to your posting I figured it all out.
    John

    1) I pass the listbox from xaml.cs to e.Commands.Add(new HelloWorldCommand(lb1 as ListBox));
    2) In HellowWorldCommand
    public class HelloWorldCommand : IPivotViewerUICommand
    {
    private readonly ListBox _lb1;

    }
    public void Execute(object parameter)
    {
    PivotViewerItem item = (PivotViewerItem)parameter;
    string itm = item.GetPropertyValue(“Name”)[0].ToString() + “,” + item.GetPropertyValue(“Profession”)[0].ToString() + “,” + item.GetPropertyValue(“City”)[0].ToString();
    // MessageBox.Show(itm);
    _lb1.Items.Add(itm);// _data.ToString()+ “,data ” );
    }

     
  14. goodcoffeegoodcode

    May 12, 2012 at 10:33 am

    Hi guys,

    Really sorry for the lack of replies by me on this thread. I’m completely tied up with my main startup, Percollate.com. Glad you’ve made progress though.

    Quick question: are you using PivotViewer in SL5 to consume existing cxml files? If you have any choice in the matter please consider using the newer data-binding model against an ObservableCollection.

    Chris

     
    • johntomaselli

      May 14, 2012 at 5:56 pm

      Thanks for the suggestion and it was next on my list and you supplied the push. I’ve just taken a caliburn.micro/devforce/ef4.1/firebird.sql project I developed and hooked it up to a pivotviewer. It works great and I can also point the image to my static collection of images from the path stored in a cxml file. In my case the images are from an art gallery collection and each one is about 10 megs so this seems like the best of both worlds. I’ve cut some of the code and TProdSupCatListViewModel represents a view from a stored procedure. In this example I’m matching productid as the key to the image and while this doesn’t make sense for the products it demonstrates the ability to do it.
      Glad to hear that Percolate is causing the delays.
      John

      d:DataContext= “{Binding Source={StaticResource ViewModelLocator}, Path=TProdSupCatListViewModel}”>

       
      • johntomaselli

        May 14, 2012 at 6:00 pm

        Code that was deleted from previous post
        < pivot:PivotViewer ItemsSource=”{Binding TProdSupCats}” >
        <pivot:PivotViewer.ItemTemplates >

        <pivot:PivotViewerMultiScaleSubImageHost ImageId=”{Binding ProductID}”
        CollectionSource=”http://www.gtz.com/pivots/MRG/mrgCollection0_files/4w50vpci.hu3.xml”
        Width=”550″
        Height=”540″>

         
  15. Masaab

    June 3, 2012 at 1:00 pm

    Any One How to implement it in MVVM View Model.

     
  16. Shaun

    June 25, 2012 at 7:33 pm

    Besides displaying a messagebox, how can you pass information from the Execute method back to the UI? Ex. creating a shopping cart custom action that adds the selected value to a listbox in the UI.

     
    • Shaun

      June 25, 2012 at 7:48 pm

      I ask this because there is no ItemActionExecuted event anymore

       

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: