helpkelp helpkelp - 1 month ago 7
C# Question

How to Call an Object Defined Within Another Page's xaml.cs (without it being new)

My question is fairly simple, but two-sided

I am aware of how to call a method by

class.method
but I am confused about how to call an object from another page. What I am trying to do is the following

UPON CLICKING
SearchBtn1Clk



  1. Read input from a
    TextBox
    , convert it to an int and set it to a variable.

  2. Use that variable to match it with the primary key content of a
    row
    within a
    DataTable
    .

  3. Navigate to a new page

  4. Take each cell in the row that was found and set it equal to an individual label on the new page.



4 is where I encounter problems. I have been spending a good three days looking through other posts, examples, tutorials, and MSDN definitions, and I still can't figure it out. One of the issues is actually getting the variable that holds the user input over to another page without it being
new
The other issue is being able to set each cell of that row to separate variables.


MainDataTable.cs

public class MainDataTable
{

public static DataTable dataMain = new DataTable("Customer Info Database");

public static void CreateTable1()
{



dataMain.Columns.Add("CustID", typeof(int));
dataMain.PrimaryKey = new DataColumn[] { dataMain.Columns["CustID"] };
dataMain.Columns.Add("CustName", typeof(string));
dataMain.Columns.Add("CustAge", typeof(int));
dataMain.Columns.Add("CustAlign", typeof(string));

DataSet MainSet = new DataSet("CustAcctsDataSet");
MainSet.Tables.Add(dataMain);
}

public static void EnterNewRows(int CustID, string CustName, int CustAge, string CustAlign)
{
dataMain.Rows.Add(CustID, CustName, CustAge, CustAlign);
}


Page2.xaml.cs

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

public void SearchBtn1Clk(object sender, RoutedEventArgs e)
{


int IDFind = Convert.ToInt32(searchIdTxtBox.Text);

DataRow foundRow = MainDataTable.dataMain.Rows.Find(IDFind);

if (foundRow != null)
{
MessageBox.Show(foundRow.ToString());
}

if (foundRow == null)
{
MessageBox.Show("No Customer Found with ID: " + IDFind);
}

this.NavigationService.Navigate(new Page3());
}


Page3.xaml.cs

public partial class Page3 : Page
{

public Page3(Page2 pg2r)
{
pg2r = this.Page2();
InitializeComponent();


}

public void SetLabels (Page2 page)
{
// pg2r.SearchBtn1Clk
CustAgeLab.Content = "";
CustIDLab.Content = "";
CustNameLab.Content = "";
CustAlgnLab.Content = "";
}

private void ReturntoMainMenu(object sender, RoutedEventArgs e)
{
this.NavigationService.Navigate(new Page0());
}
}


Thanks!

Answer

In order for you to take full advantage of MvvM and Binding when using WPF would be:

  1. Create Model, That's your MainDataTable class
  2. Create View Model, this is responsible for providing data for your View
  3. Create View , that part you already have.

Here is how ViewModel looks like:

namespace WpfApplication1
{
    public class MainVM : INotifyPropertyChanged
    {
        public MainVM()
        {
            InitialiseComponents();
        }

        private void InitialiseComponents()
        {
            LoginCommand = new RelayCommand(loginCommandMethod);
        }

        private string searchKey;

        public string SearchKey
        {
            get { return searchKey; }
            set { searchKey = value; OnPropertyChanged("SearchKey"); }
        }

        private RelayCommand _loginCommand;

        public RelayCommand LoginCommand
        {
            get { return _loginCommand; }
            private set { _loginCommand = value; }
        }

        private void loginCommandMethod(object parameter)
        {
            // do something
        }

        #region INotify
        public void OnPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
        public event PropertyChangedEventHandler PropertyChanged; 
        #endregion
    }
}

and here is the RelayCommand:

namespace WpfApplication1.Commands
{
    public class RelayCommand : ICommand
    {
        private Action<object> _execute;
        private Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged;

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

        public void Execute(object parameter)
        {
            _execute.Invoke(parameter);
        }
    }
}  

At this point you have the Page2.xaml and your ViewModel so let's make them work together:

<Page x:Class="WpfApplication1.Views.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:WpfApplication1.Views"
  mc:Ignorable="d" 
  d:DesignHeight="300" d:DesignWidth="300"
  Title="Page2">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <TextBox Text="{Binding SearchKey, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Content="Search" Command="{Binding SearchCommand}"/><!--There is an example of command in VM already called login command-->
</Grid>

Now in order for you to use Page you need to use Frame so let's call it in the MainWindow.xaml:

<Window x:Class="WpfApplication1.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:WpfApplication1"
    xmlns:views="clr-namespace:WpfApplication1.Views"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<!--<Window.DataContext>
    <local:MainVM/>
</Window.DataContext>-->
<Window.Resources>
    <local:MainVM x:Key="mainVM"/>
    <local:LoginPage x:Key="login" DataContext="{StaticResource mainVM}"/>
    <views:Page2 x:Key="SearchPage" DataContext="{StaticResource mainVM}"/>
    <!---->
    <ControlTemplate x:Key="ctrlTmpl">
        <local:LoginPage/>
    </ControlTemplate>

</Window.Resources>
<Grid>
    <!--<Button x:Name="button" Content="Do something" Click="btnDoSomething" HorizontalAlignment="Left" Margin="221,60,0,0" VerticalAlignment="Top" Width="75"/>-->
    <!--<Control Template="{StaticResource ctrlTmpl}"/> This works-->
    <Frame Content="{StaticResource SearchPage}"/>
</Grid>

I honestly don't know what is happening and I can't post the rest of the code.
It is available for you on GitHub though through this Git Hub Link

Comments