0

I have been all over the internet looking for a clear answer and cannot find one. I have created Window Forms apps in the past, and decided to give WPF a try. I am hoping I don't have to move back to WinForms, but cannot figure out the simplest tasks.

How do I pass text in Page1's Textbox to Page2's TextBox.

I apologize if this is a duplicate, but I cannot find a clear answer anywhere. Most beginner mvvm tutorials seem to stick to one page apps.

MainWindo.xaml

<Window x:Class="WpfApp3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="/Page1.xaml"/>
    </Grid>
</Window>

Page1 Xaml:

<Page x:Class="WpfApp3.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfApp3"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="Page1"
      xmlns:vm="clr-namespace:WpfApp3">
    <Page.DataContext>
        <vm:Page1ViewModel/>
    </Page.DataContext>
    <Grid>

        <StackPanel>
            <TextBlock Margin="20" FontSize="36">Welcome Home</TextBlock>
            <TextBox x:Name="UserName" Margin="10 0 10 0" Text=""/>
            <Button x:Name="Next" Margin="10 10" Content="Next" Click="Next_Click"/>
        </StackPanel>

    </Grid>
</Page>

Page1 Code-Behind:

using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }
        private void Next_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(
                new Uri("/Page2.xaml", UriKind.Relative));
        }
    }
}

Page1 ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp3
{
    class Page1ViewModel : Notifier
    {
        private string username;
        public string UserName
        {
            get { return username; }
            set
            {
                username = value;
                OnPropertyChanged("UserName");
            }
        }

    }
}

Page2 Xaml:

<Page x:Class="WpfApp3.Page2"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfApp3"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="Page2"
      xmlns:vm="clr-namespace:WpfApp3>
      <Page.DataContext>
          <vm:Page2ViewModel/>
      <Page.Data.Context>


    <Grid>
        <StackPanel>
            <TextBlock Margin="10">Hello there: </TextBlock>
            <TextBox x:Name="TextBox_Name" Margin="10" Text="{Binding UserName}"/>
        </StackPanel>
    </Grid>
</Page>

Page2 Code-behind:

using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for Page2.xaml
    /// </summary>
    public partial class Page2 : Page
    {
        public Page2()
        {
            InitializeComponent();   
        }
    }
}

Page2 View Model:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp3
{
    class Page2ViewModel : Notifier
    {
        private string textbox_name;
        public string TextBox_Name
        {
            get { return textbox_name; }
            set
            {
                textbox_name = value;
                OnPropertyChanged("TextBox_Name");
            }
        }
    }
}
Mwspencer
  • 1,142
  • 3
  • 18
  • 35
  • I have no experience with more than one window / page I usually have a single window and what is changed in it are my views, which in turn are assigned to a viewmodel, so when I need to pass something from one view to another I send it through constructor of the viewmodel that will receive and handle the data, I think this is called Dependency Injection – Celso Lívero Mar 14 '18 at 15:42
  • Is that similar to what I have here? I have a single window that starts on Page1, then a button that navigates to Page2. – Mwspencer Mar 14 '18 at 16:00
  • [take a look here](https://stackoverflow.com/a/47675372/5605739) – Celso Lívero Mar 14 '18 at 16:23
  • You should properly implement the navigation service, i suggest that you use an mvvm library (mvvmlight is one of the easiest ones), then take a look at the answer here https://stackoverflow.com/questions/28966819/mvvm-light-5-0-how-to-use-the-navigation-service/28968560#28968560 – SamTh3D3v Mar 14 '18 at 16:28

1 Answers1

1

first of all you don't need to move back to WinForms: you can avoid MVVM alltogether and use the traditional code-behind coding model you know even with WPF. I'd suggest doing so for your first WPF applications if you don't feel at ease with MVVM.

As for your problem, a solution could be to use static properties for common values storage.

public class MyCommonValues
{
  public static string SharedText { get; set; }
}

class Page1ViewModel : Notifier
{
    private string username;
    public string UserName
    {
        get { return username; }
        set
        {
            username = value;
            OnPropertyChanged("UserName");
            OnUserNameChanged(); // added to your code
        }
    }

    // following is an addition to your code
    void OnUserNameChanged()
    {
      MyCommonValues.SharedText = UserName;
    }
}

class Page2ViewModel : Notifier
{
    // following is an addition to your code
    public Page2ViewModel()
    {
      TextBox_Name = MyCommonValues.SharedText;
    }

    private string textbox_name;
    public string TextBox_Name
    {
        get { return textbox_name; }
        set
        {
            textbox_name = value;
            OnPropertyChanged("TextBox_Name");
        }
    }
}
Arnaud Weil
  • 2,324
  • 20
  • 19
  • 1
    Perfect thank you, that shared value was the secret sauce, makes much more sense now of how to bind the UI values to the VM variables and vice versa. – Mwspencer Mar 16 '18 at 17:26
  • It will take a little more practice but you're getting there quickly! – Arnaud Weil Mar 18 '18 at 16:12