Adding in the LightSwitch pivot viewer an adorner for communicating with the regular lightswitch screens.

Introduction

This post is part of a series on the usage of the pivot viewer in LightSwitch.

In this post, we will add two adorners to the pivot viewer card in such a way the user can open a modal window for editing the current movie and for viewing the cast of the current movie.

Show me such an adorner

What will clicking the adorner trigger?

When we click “edit”:

and when we click “cast”:

 

How do we setup an adorner?

We first need to add a style to our custom control’s resources:

<Style x:Key="basicAdorner" TargetType="pivot:PivotViewerItemAdorner">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <pivot:PivotViewerDefaultItemAdorner
                    IsItemSelected="{Binding IsItemSelected, RelativeSource={RelativeSource TemplatedParent}}"
                    CommandsRequested="basicAdorner_CommandsRequested" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

This style will make sure an event triggered where we setup the Commands that we want to fire when the adorner is clicked.

In the custom control’s code behind we setup this event:

 private void basicAdorner_CommandsRequested(object sender, System.Windows.Controls.Pivot.PivotViewerCommandsRequestedEventArgs e)
        {
            if (e.IsItemSelected)
            {
                IContentItem currentDataContext = (IContentItem)this.DataContext;
                e.Commands.Add(new EditMovieDetailsCommand(currentDataContext));
                e.Commands.Add(new showCastCommand(currentDataContext));
            }
        }

As you can see I forward the screen’s datacontext via the constructor to the command.

Such a command is simply a pivot viewer specific implementation of ICommand.

For the “edit movie” command we need:

    public class EditMovieDetailsCommand : IPivotViewerUICommand
    {
        IScreenObject _screen;
        public EditMovieDetailsCommand(IContentItem screenDataContext)
        {
            _screen = (IScreenObject)screenDataContext.Screen;
        }

        public string DisplayName
        {
            get { return "Edit"; }
        }

        public Uri Icon
        {
            get { return null; }
        }

        public object ToolTip
        {
            get { return "Edit the movie details"; }
        }

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

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {

            IEntityObject entity = parameter as IEntityObject;
            int movieId = (int)(entity.Details.Properties["Id"].Value);
            _screen.Details.Dispatcher.BeginInvoke(() =>
            {
                _screen.Details.Properties["CurrentMovieId"].Value = movieId;
                _screen.Details.Methods["ShowDetails"].CreateInvocation(null).Execute();
            });
        }
    }

And for the “Show Cast” command we need:

 public class showCastCommand : IPivotViewerUICommand
    {
        IScreenObject _screen;
        public showCastCommand(IContentItem screenDataContext)
        {
            _screen = (IScreenObject)screenDataContext.Screen;
        }

        public string DisplayName
        {
            get { return "Cast"; }
        }

        public Uri Icon
        {
            get { return null; }
        }

        public object ToolTip
        {
            get { return "Show the list of actors"; }
        }

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

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {

            IEntityObject entity = parameter as IEntityObject;
            int movieId = (int)(entity.Details.Properties["Id"].Value);
            _screen.Details.Dispatcher.BeginInvoke(() =>
            {
                _screen.Details.Properties["CurrentMovieId"].Value = movieId;
                _screen.Details.Methods["ShowCast"].CreateInvocation(null).Execute();
            });
        }
    }

As you can see, the Execute method is the most involved. In the execute method we will communicate with the hosting LightSwitch screen where we created two modal forms:

 

Obviously, we need to call the OpenModalWindow method:

namespace LightSwitchApplication
{
    public partial class MoviePivot
    {
        partial void ShowDetails_Execute()
        {
            this.OpenModalWindow("ModalMovie");
        }

        partial void ShowCast_Execute()
        {
            this.OpenModalWindow("ModalCast");
        }
    }
}

Conclusion

Setting up an adorner is a bit more work, but the result is great with minimal effort, since we re-use the standard LightSwitch screens for enriching the semantic zoom experience.