Navigation not working in Silverlight?

Coordinator
Nov 28, 2011 at 7:41 PM

I tried passing the selected ListeItem Id as parameter to my EditView like this:
 

private void OnCommandEditMessage(object parameter) {
    Dictionary<string, object> parameters = new Dictionary<string, object>();
    parameters.Add("MessageId", parameter);
    var navigationService = GetService<INavigationService>();
    navigationService.Navigate<EditMessageViewModel>(parameters);
}

 
In the EditMessageViewModel i have overwritten the OnNavigationCompleted method.
The View is displayed, no Errors in Output, but the Method never get's called?
 

protected override void OnNavigationCompleted() {
    var service = DBUpdateServiceFactory.GetDBUpdateService();
    if (NavigationContext.ContainsKey("MessageId")) {
        int theKey = (int)NavigationContext["MessageId"];
        service.GetMessageCompleted += new System.EventHandler<GetMessageCompletedEventArgs>(service_GetMessageCompleted);
        service.GetMessageAsync(theKey);
    }
}

 
What could be wrong?

Coordinator
Nov 28, 2011 at 7:46 PM

Are you sure you are using page navigation in your silverlight application? In the examples of catel (see http://catelexamples.codeplex.com), there is an example application with navigation which works. It uses the following code:

/// <summary>
/// Method to invoke when the NavigateToAboutViaViewModel command is executed.
/// </summary>
/// <param name="parameter">The parameter of the command.</param>
private void OnNavigateToAboutViaViewModelExecute(object parameter)
{
    var parameters = new Dictionary<string, object>();
    parameters.Add("Data", "navigated from home");

    var navigationService = GetService<INavigationService>();
    navigationService.Navigate<AboutViewModel>(parameters);
}

Then, it uses the same data like this:

protected override void OnNavigationCompleted()
{
    NavigationData = string.Empty;
    if (NavigationContext.ContainsKey("Data"))
    {
        NavigationData = NavigationContext["Data"] as string;
    }
}

Make sure that you have derived your page from the Page<TViewModel> class, not from the UserControl<TViewModel> class.

Nov 28, 2011 at 7:49 PM

Thanks - I got it:

in a Silverlight Project we need to override the Inizialize Method.
The OnNavigationCompleted event does not get called?

I wonder, why it's called in the About and the Homepage of the Demoapplication?

I built my page exactly using this schema?

Greets - Helmut

 

Coordinator
Nov 28, 2011 at 7:50 PM

Those were the default generated pages in the silverlight template, we decided to use the same for our example. If you switch back and forth between the pages, you will see that the data is transferred.

Nov 28, 2011 at 8:01 PM

Yes I see.

And page looks exactrly the same.

this is the code behind for the EditMessage.xaml

    /// <summary>
    /// Interaction logic for CreateMessage.xaml.
    /// </summary>
    public partial class EditMessage : EditMessageIntermediate {
        /// <summary>
        /// Initializes a new instance of the <see cref="CreateMessage"/> class.
        /// </summary>
        public EditMessage() {
            InitializeComponent();
        }
    }

    /// <summary>
    /// Intermediate class for CreateMessage since Silverlight doesn't support generic base classes.
    /// </summary>
    public class EditMessageIntermediate : Page<EditMessageViewModel> {

    }

The EditMessageViewModel is derived from ViewModelBase basically this should be simple - or not?



   public class EditMessageViewModel : ViewModelBase {
        /// <summary>
        /// Initializes a new instance of the <see cref="EditMessageViewModel"/> class.
        /// </summary>
        public EditMessageViewModel() {
            CommandSave = new Command<object>(OnCommandSave);
            CommandCancel = new Command<object>(OnCommandCancel);
         }

        /// <summary>
        /// Gets the title of the view model.
        /// </summary>
        /// <value>The title.</value>
        public override string Title { get { return "Edit Message"; } }

        /// <summary>
        /// Gets or sets the navigation data.
        /// </summary>
        public MessageItem MessageItem { get; private set; }

        #region Methods

        protected override void  OnNavigationCompleted() {

            if (NavigationContext.ContainsKey("MessageId")) {
                int theKey = (int)NavigationContext["MessageId"];
                var service = DBUpdateServiceFactory.GetDBUpdateService();
                service.GetMessageCompleted += new System.EventHandler<GetMessageCompletedEventArgs>(service_GetMessageCompleted);
                service.GetMessageAsync(theKey);
            }
        }

        void service_GetMessageCompleted(object sender, GetMessageCompletedEventArgs e) {
            MessageItem = e.Result;
            if (MessageItem != null) {
                OnViewModelPropertyChanged(this, "MessageItem");
            } else {
                var navigationService = GetService<INavigationService>();
                navigationService.Navigate<MessageListViewModel>();
            }
        }

        #endregion

        // TODO: Register models with the vmpropmodel codesnippet
        // TODO: Register view model properties with the vmprop or vmpropviewmodeltomodel codesnippets
        // TODO: Register commands with the vmcommand or vmcommandwithcanexecute codesnippets

        /// <summary>
        /// Gets the NavigateToMessages command.
        /// </summary>
        public Command<object> CommandSave { get; private set; }

        /// <summary>
        /// Method to invoke when the NavigateToAboutViaViewModel command is executed.
        /// </summary>
        /// <param name="parameter">The parameter of the command.</param>
        private void OnCommandSave(object parameter) {

            var service = DBUpdateServiceFactory.GetDBUpdateService();
            service.UpdateMessageAsync(MessageItem);
            service.UpdateMessageCompleted += new System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(service_UpdateMessageCompleted);
            service.CloseAsync();

        }

        void service_UpdateMessageCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) {
            var messageService = GetService<IMessageService>();
            messageService.ShowInformation("The Item has been updated...", "Info", ((Action)(() => {
                OnCommandCancel(MessageItem.MessageId);
            })));
        }



        /// <summary>
        /// Gets the NavigateToMessages command.
        /// </summary>
        public Command<object> CommandCancel { get; private set; }

        /// <summary>
        /// Method to invoke when the NavigateToAboutViaViewModel command is executed.
        /// </summary>
        /// <param name="parameter">The parameter of the command.</param>
        private void OnCommandCancel(object parameter) {
            var navigationService = GetService<INavigationService>();
            navigationService.Navigate<MessageListViewModel>();
        }
    }

The OnNavigationCompleted event never gets called.

Only the Initialize event get's called, but here the NavigationContext has no parameters.

If you have Skype we I can show you it's not working on my side :-)

 

 

 

Nov 28, 2011 at 8:31 PM

Update:

In between I did the following:

Added a new ViewModel called EditMessageIIViewModel.
Added a new Silverlight Page.

Navigation worls, View is displayed,

OnNavigationCompleted not called, parameters not in NavigationContext.



    public class EditMessageIIViewModel : ViewModelBase {
        /// <summary>
        /// Initializes a new instance of the <see cref="EditMessageIIViewModel"/> class.
        /// </summary>
        public EditMessageIIViewModel() {
        }

        protected override void OnNavigationCompleted() {
            int id = (int)NavigationContext["MessageId"];
        }

        /// <summary>
        /// Gets the title of the view model.
        /// </summary>
        /// <value>The title.</value>
        public override string Title { get { return "View model title"; } }

        // TODO: Register models with the vmpropmodel codesnippet
        // TODO: Register view model properties with the vmprop or vmpropviewmodeltomodel codesnippets
        // TODO: Register commands with the vmcommand or vmcommandwithcanexecute codesnippets
    }
The Page:
<Views:EditMessageIIIntermediate x:Class="RomanticaWeb.Views.EditMessageII"
                      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
					  xmlns:catel="http://catel.codeplex.com"
					  xmlns:Views="clr-namespace:RomanticaWeb.Views">
    
    <!-- Resources Note that in the template it's called Page:Resources - that didn't work -->
    <Views:EditMessageIIIntermediate.Resources>
    </Views:EditMessageIIIntermediate.Resources>

    <!-- Content -->
    <Grid>
        <TextBlock Text="Here goes your real content" />
    </Grid>
</Views:EditMessageIIIntermediate>

    public partial class EditMessageII : EditMessageIIIntermediate {
        /// <summary>
        /// Initializes a new instance of the <see cref="EditMessageII"/> class.
        /// </summary>
        public EditMessageII() {
            InitializeComponent();
        }
    }

    /// <summary>
    /// Intermediate class for EditMessageII since Silverlight doesn't support generic base classes.
    /// </summary>
    public class EditMessageIIIntermediate : Page<EditMessageIIViewModel> {
        /// <summary>
        /// Initializes a new instance of the <see cref="EditMessageIIIntermediate"/> class.
        /// </summary>
        /// <remarks>
        /// This constructor can only be used for design-time support. An exception will be thrown when it is used
        /// outside a designer.
        /// </remarks>
        public EditMessageIIIntermediate() { }
    }
I will Stop for Today. <!-- Resources --> <!-- Content -->

Greets - Helmut

Coordinator
Nov 29, 2011 at 8:28 AM

Strange, I will try to reproduce this tonight.

Nov 29, 2011 at 2:03 PM

Hi Geert,

some news:

I was not sure if my problem is in my  Project, so I decided to create a new Project.
This is what I did:

Created a new Silverlight Project using the Template: Silverlight/Catel/Silverlight Navigation Application with Catel

After the Project has been created, the Catel reference is missing, so I added it using thbe NuGet Package-Manager.

The project compiled, the Navigation is working, in th eBrowser I can see the Url and the Parameter like this:

http://localhost:4463/SilverlightApplication1TestPage.aspx#/Views/About.xaml?Data=navigated+from+home

But- I set a Breakpoint in the AboutViewModel.cs and the OnNavigationCompleted Method never get's called.

So - from my point of view it's a general Problem in the NavigationEngine, passing Parameters in Silverlight does not work at all.
Greets - Helmut

 

Coordinator
Nov 29, 2011 at 7:21 PM
Edited Nov 29, 2011 at 7:25 PM

Found the issue, it was indeed a bug in SL (WP7 works fine). You can find a new beta version here:

http://dl.dropbox.com/u/8455721/Catel%20beta.zip

Sorry for the inconvenience.