8

I am trying to pass a simple string between pages but I don't know how to.

I created a test app where I click a button, the the value of "a" will pass on the next page (Page1.xaml.cs)

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        string a = "hello";

        Page2 p2 = new Page2();
        NavigationService.Navigate(p2, a);
    }

Now, I want to extract the data from Page1 (Page2.xaml.cs)

    private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
    {
        string str = (string)e.ExtraData;
    }

And then subscribing in the constructor (Page2.xaml.cs)

    public Page2()
    {
        InitializeComponent();
        NavigationService.LoadCompleted += NavigationService_LoadCompleted;
    }

However when I ran the program I get an error. Can someone point out what am I missing?

syn3rgy
  • 115
  • 1
  • 1
  • 11
  • There is already a similar question is SO [here](http://stackoverflow.com/questions/37955612/how-can-i-transfer-parameter-from-one-page-to-another/37977367#37977367). – Hasan Hasanov Jul 08 '16 at 06:20

3 Answers3

4

Without a good Minimal, Complete, and Verifiable code example, it's impossible to know for sure everything that would be needed to address your question. However, if all you're asking is how to allow data to pass from one page to the next when navigating, it seems to me that the NavigationService.Navigate(object, object) overload would be useful for you.

The second parameter is the data you want to pass. The target page can handle the NavigationService.LoadCompleted event (or any other appropriate one you prefer), where the object value that was passed to the Navigate() method can be retrieved via the NavigationEventArgs.ExtraData property.

For example, in your first page:

private void button_Click(object sender, RoutedEventArgs e)
{
    Page2 p2 = new Page2();
    NavigationService.Navigate(p2, v.str);
}

then in your second page:

private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
{
    string str = (string)e.ExtraData;

    // do whatever with str, like assign to a view model field, etc.
}

Of course, you'll subscribe the event handler, e.g. in your page's constructor or in XAML. For example:

public partial class Page2 : Page
{
    public Page2()
    {
        InitializeComponent();

        NavigationService.LoadCompleted += NavigationService_LoadCompleted;
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        NavigationService.GoBack();
    }

    private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
    {
        string str = (string)e.ExtraData;

        // do whatever with str, like assign to a view model field, etc.
    }
}
Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • 1
    can you elaborate more about subscribing the event handler .. Im a little of a beginner when coding in this language – syn3rgy Jul 09 '16 at 06:54
  • See edit above, for example of subscribing in the constructor. That should work fine, but if you find `NavigationService` is `null` at that point, you might have to move the code into a handler for the `Page.Loaded` event (subscribed to in a similar way, i.e. `Loaded += Page_Loaded`, where there is a `void Page_Loaded(object sender, RoutedEventArgs e)` method in your `Page2` class...but hopefully you won't need to do it that way). – Peter Duniho Jul 09 '16 at 07:06
  • I followed the code above and got a null. Then I did what you mentioned again, but I am not sure if I did it right. What I did is created `private void Page_Loaded(object sender, RoutedEventArgs e)` and in it `NavigationService.LoadCompleted += NavigationService_LoadCompleted;` . Then wrote `Loaded += Page_Loaded;` in `public Page2()` – syn3rgy Jul 11 '16 at 04:20
  • Got `null` where? After you added the event handlers in your code, did you set breakpoints to see if they are being called? I can't comment specifically without a good [mcve]. Feel free to improve your question by editing it so that it includes an MCVE showing the state of the code. – Peter Duniho Jul 11 '16 at 04:23
  • 2
    On the `NavigationService.LoadCompleted += NavigationService_LoadCompleted;`. When I run the program and click the Button, I get "NullReferenceException was unhandled". No i didn't, as a beginner I didn't even know I could set a breakpoints. – syn3rgy Jul 11 '16 at 04:51
  • See http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it for help understanding the `NullReferenceException`. It won't do any good to ask anyone (me or anyone else) just about the exception; without context, it's meaningless. You can debug the exception so that you understand _what_ is causing it, then you can ask for help fixing it. In any case, all of this can be addressed if you'd provide a good [mcve]. – Peter Duniho Jul 11 '16 at 04:56
  • I have edited my post above, is that a good Minimal, Complete, and Verifiable example? I'm sorry for asking so many questions and help. – syn3rgy Jul 12 '16 at 07:10
  • No, you have not provided an MCVE. Please read the page [mcve] to understand what is meant by "Minimal, Complete, and Verifiable" and it's important. – Peter Duniho Jul 12 '16 at 15:10
  • On the case of `NullReferenceException`, put `NavigationService.LoadCompleted += NavigationService_LoadCompleted;` inside the `Page_Loaded()` event will solve the problem. – dwpessoa Mar 03 '23 at 12:06
-1

Instead of setting the textbox DataContext, set the entire page’s datacontext to some class ie the ViewModel for page1. Implement the interface INotifyPropertyChanged and ensure that in the set of the string property, the NotifyPropertyChanged(“ElementName”) is raised.

Now create a new view with a corresponding view model like this which should also implement the interface INotifyPropertyChanged. Create a textbox and bind it to a string property like in first page. Ensure TwoWay binding for both properties to ensure both target and source is updated while data is changed.

Create the instance of both viewModels in MainWindow. When user navigates to 2nd user control, set

Page2ViewModel.TextBoxString = Page1ViewModel.TextBoxString;

Like this do vice versa while navigating from Page2 to Page1.

Page1ViewModel.TextBoxString = Page2ViewModel.TextBoxString;

This way, both the textboxes will be updated during navigation. This is just an overall idea. You need to learn more about MVVM and WPF from some tutorials. Search in google.

ViVi
  • 4,339
  • 8
  • 29
  • 52
-1

Here is my example, maybe it helps someone

in Page1.cs

examsStr = result.Content.ReadAsStringAsync().Result;
List<Exam> exams = JsonConvert.DeserializeObject<List<Exam>>(examsStr);
for (int i = 0; i < exams.Count; i++)
{
    btnExam.Click += BtnExam_OptionsShow;
    btnExam.DataContext = exams[i];
}
private void BtnExam_OptionsShow(object sender, EventArgs e)
{
        ExamRead examPage = new ExamRead();
        examPage.DataContext = ((sender as Button).DataContext as Exam);
        this.NavigationService.Navigate(examPage);
}

in Page2.cs

this.Loaded += ExamRead_Loaded;

private void ExamRead_Loaded(object sender, RoutedEventArgs e)
{

     examObj = (exam.DataContext as Exam);
     (exam.Children[2] as Label).Content = examObj.ExamName + " - Exam Options";
}

Page2 has attribute Name="exam" and examObj is global variable in that Page2 class