C# Passing data Between windows(WPF) - c#

Recently picked up C# in university, trying to work out how to pass the variable "name" in MainWindow.xaml to ThirdWindow.xaml?
The below code is for the main window where the data is assigned to the variable "name"
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void NameBox_TextChanged(object sender, TextChangedEventArgs e)
{
string name = NameBox.Text;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
SecondWindow newWin = new SecondWindow();
newWin.Show();
this.Close();
}
}
The below code is for the third window
public partial class ThirdWindow : Window
{
public ThirdWindow()
{
InitializeComponent();
}
public void LstThanks_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LstThanks.Items.Add(name);
}
}

You can simply pass that string name variable in the constructor as an argument to the ThirdWindow on Button_Click event.
private void Button_Click(object sender, RoutedEventArgs e)
{
var name = "your name";
var newWin = new ThirdWindow(name);
newWin.Show();
this.Close();
}
That string text will be available in the constructor of ThirdWindow.
public partial class ThirdWindow: Window
{
public ThirdWindow(string name)
{
InitializeComponent();
}
public void LstThanks_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LstThanks.Items.Add(name);
}
}

You can pass the variable through the constructor of the new window
var win = new ThirdWindow(name);
public ThirdWindow(string name)
{
InitializeComponent();
}
Another method is to pass it through an event message. This will require you to write a new message and add an event listener to your constructor in the ThirdWindow class. If you google this there are a variety of examples out there on how to do such a thing.

Here you are defining a local variable name. This variable is visible only inside the {} block. So we cannot use it anywhere else.
public void NameBox_TextChanged(object sender, TextChangedEventArgs e)
{
string name = NameBox.Text;
}
You could add a new string property into second window and pass value through that to all the way into third form.
So, add new property into your two windows (SecondWindow, ThirdWindow)
public string Name { get; set; }
These properties are holding the data for whole their lifetime (until they are closed).
Remove NameBox_TextChanged event handling, because we don't need it.
Add property setting inside your buttons click event
private void Button_Click(object sender, RoutedEventArgs e)
{
SecondWindow newWin = new SecondWindow();
newWin.Name = NameBox.Text; //Store value into SecondWindow variable
newWin.Show();
this.Close();
}
Now when SecondWindow is visible (Show is called), you have name value available in Name variable and you should be able to copy this behavior for ThirdWindow.

If the ThirdWindow window is dependent on the name value then you can pass it through the constructor:
public partial class ThirdWindow : Window
{
public string Name { get; set; }
public ThirdWindow(string name)
{
InitializeComponent();
Name = name;
}
}
or if not then make a method on the ThridWindow to set the name:
public partial class ThirdWindow : Window
{
public string Name { get; set; }
public void SetName(string name)
{
Name = name;
}
}

Related

Putting information from one window to a datagrid in another window without the use of database

So my MainWindow with a datagrid is suppose to have an "add client" button and it will bring you to a new window and that window will ask information about the soon to be client and if I click the "save" button it should close the window and put the information to the datagrid on my MainWindow and I tried many things but I can't seem to get it right and I'm using wpf
public partial class GetInfo : Window
{
public GetInfo()
{
InitializeComponent();
}
public class Client
{
public string name { get; set; }
public string address { get; set; }
}
private void SaveBT_Click(object sender, System.EventArgs e)
{
MainWindow main = new MainWindow();
Client addClient = new Client();
addClient.name = NameTB.Text;
addClient.address = AddressTB.Text;
main.DataGridXAML.Items.Add(addClient);
this.Close();
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
private void LogOut_Click(object sender, RoutedEventArgs e)
{
LoginScreen logout = new LoginScreen();
logout.Show();
Close();
}
private void AddClient_Click(object sender, RoutedEventArgs e)
{
GetInfo infoget = new GetInfo();
infoget.Show();
}
}
Seems like your GetInfo is working like a dialogue.
You may store the info in GetInfo and get info after user choose closed.
In your MainWindow
private void AddClient_Click(object sender, RoutedEventArgs e)
{
GetInfo infoget = new GetInfo();
infoget.ShowDialog();
if( get.DialogResult != true ) {
return;
}
main.DataGridXAML.Items.Add(addClient);
}
In GetInfo
public partial class GetInfo : Window
{
public GetInfo()
{
InitializeComponent();
}
public class Client
{
public string name { get; set; }
public string address { get; set; }
}
// Save info in window as a property.
public Client Info { get; set; }
private void SaveBT_Click(object sender, System.EventArgs e)
{
Client addClient = new Client();
addClient.name = NameTB.Text;
addClient.address = AddressTB.Text;
Info = addClient;
DialogueResult = true;
}
}
What's wrong with your original code? Look at comments below.
private void SaveBT_Click(object sender, System.EventArgs e)
{
// This is the problem, this main is NOT your actual instance of MainWindow which calls this GetInfo.
MainWindow main = new MainWindow();
Client addClient = new Client();
addClient.name = NameTB.Text;
addClient.address = AddressTB.Text;
main.DataGridXAML.Items.Add(addClient);
this.Close();
// After this command, main is not getting used anymore, so you get nothing in your actual MainWindow
}

How to change textbox value when I change it from another window [duplicate]

This question already has answers here:
Change a textbox's text value on a UserControl from a Window in WPF
(2 answers)
Closed 3 years ago.
Ok, I have two windows in my WPF app. I want to change the text of a textbox, from a second window. This should also happen parallel.
I know, this is about multithreadin, but I know very little about it.
This is what my current code looks like, but this is for copying textbox text.
private void copyButton_Click(object sender, RoutedEventArgs e)
{
secondWindow = new SecondWindow();
secondWindow.textBoxS.Text = textBox.Text;
secondWindow.Show();
}
But, I want to change textbox texts dynamically between the MainWindow and the Second window.
So I tried something like this:
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
Task t = Task.Run(() =>
{
secondWindow = new SecondWindow();
secondWindow.textBoxS.Text = textBox.Text;
secondWindow.Show();
});
t.Start();
}
There are several ways to do this. I put two way in below:
Method 1
You can create a public method (e.g. SetTextBoxValue) and
pass the window that contains the TextBox to other window. Then change the TextBox value using that method. like this:
MainWindow
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
public void SetTextBoxValue(string value)
{
SampleTextBox.Text = value;
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var otherWindow = new AnotherWindow(this);
otherWindow.Show();
}
}
Other Window
public partial class AnotherWindow
{
private readonly MainWindow _mainWindow;
public AnotherWindow(MainWindow mainWindow)
{
_mainWindow = mainWindow;
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
_mainWindow.SetTextBoxValue("New value from other window");
}
}
Method 2
You can create a event for other window and subscribe to it in main window. like this:
MainWindow
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var otherWindow = new AnotherWindow();
otherWindow.TextBoxValueChanged += OtherWindowOnTextBoxValueChanged;
otherWindow.Show();
}
private void OtherWindowOnTextBoxValueChanged(object sender, TextBoxValueEventArgs e)
{
SampleTextBox.Text = e.NewValue;
}
}
Other Window
public partial class AnotherWindow
{
public event EventHandler<TextBoxValueEventArgs> TextBoxValueChanged;
public AnotherWindow()
{
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var newValue = "New value from other window";
OnTextBoxValueChanged(new TextBoxValueEventArgs(newValue));
}
protected virtual void OnTextBoxValueChanged(TextBoxValueEventArgs e)
{
TextBoxValueChanged?.Invoke(this, e);
}
}
public class TextBoxValueEventArgs : EventArgs
{
public string NewValue { get; set; }
public TextBoxValueEventArgs(string newValue)
{
NewValue = newValue;
}
}
OUTPUT
try this, initialize the second window in first window constructor
private SecondWindow _secondWindow;
public FirstWindow()
{
_secondWindow = new SecondWindow();
}
and your second form before constructor
private string text;
public string Text
{
get
{
return text;
}
set
{
textBoxOfSecondWindow.Text = value;
text = value;
}
}
then in the copybutton function
private void copyButton_Click(object sender, RoutedEventArgs e)
{
_secondWindow.Text= textBox.Text;
_secondWindow.Show();
}
in the textchange of the first window
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
_secondwindow.Text = textBox.Text;
}
in your second window, place this code in the textBox_TextChanged method.
((MainWindow)Application.Current.MainWindow).txtFirstWindow.Text = txtSecondWindow.Text;

C# Trying to access textbox on form through a new class

Still in the process of learning C#, but I'm a bit confused on something here.
For example, I have a textbox on my form and it has the name of testTXT. Based on the code below, I've created a new class outside of the public partial one that's there by default, and now I'm trying to access testTXT but I cannot. I'm going to also need to access several other textboxes and things later on as well.
Here's a snippet of the code I'm working with thus far:
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass();
gc.CreatePackage("C:\\Users\\user\\Downloads\\output.docx");
}
private void browseButton_Click(object sender, EventArgs e)
{
var fsd = new FolderSelect.FolderSelectDialog();
fsd.Title = "Select folder to save document";
fsd.InitialDirectory = #"c:\";
if (fsd.ShowDialog(IntPtr.Zero))
{
testTXT.Text = fsd.FileName;
}
}
}
public class GeneratedClass
{
**trying to access testTXT right here, but can't.**
}
}
Any help would be greatly appreciated.
You could do this (see other answers), but you really shouldn't.
Nobody but the containing form has to know about the textboxes in it. Who knows, they might disappear, have their name changed, etc. And your GeneratedClass could become a utility class used by lots of forms.
The appropriate way of doing this, is to pass whatever you need from your textbox to your class, like so:
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass();
gc.CreatePackage(this.testTxt.Text);
}
public class GeneratedClass
{
public void CreatePackage(string name) { // DoStuff! }
}
This is because you have your TextBox type defined in Form1 class as private member. Thus can't be access with another class instance
Your question has little to do with C#, more to do with Object Oriented Concepts.
Instance of TextBox has to be given to 'GeneratedClass' somehow.
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass(testTXT);
gc.DoSomething();
gc.CreatePackage("C:\\Users\\user\\Downloads\\output.docx");
}
private void browseButton_Click(object sender, EventArgs e)
{
var fsd = new FolderSelect.FolderSelectDialog();
fsd.Title = "Select folder to save document";
fsd.InitialDirectory = #"c:\";
if (fsd.ShowDialog(IntPtr.Zero))
{
testTXT.Text = fsd.FileName;
}
}
}
public class GeneratedClass
{
TextBox _txt;
public GeneratedClass(TextBox txt)
{
_txt= txt;
}
public void DoSomething()
{
txt.Text = "Changed the text";
}
}
}
You must make testTXT public.
See Protection level (Modifiers) of controls change automaticlly in .Net.
And access to TextBox as
public class GeneratedClass
{
GeneratedClass(Form1 form)
{
form.testTXT.Text = "1";
}
}

using combobox to display data to child form

I have two child forms. The first form (Employee) has all the textboxes and a button to open another child form called Search. The Search form has a combobox. After user selects data from combobox then the data from combobox will display in Employee form.
Employee Form:
public string s;
protected override void OnShown(EventArgs e)
{
txtName.Text = s;
base.OnShown(e);
}
Search Form:
private void cbFind_SelectedValueChanged(object sender, EventArgs e)
{
if (cbFind.SelectedItem != null)
{
emp em = new emp();
em.s = cbFind.SelectedItem.ToString();
em.ShowDialog();
}
}
I do not want another Employee form to open after user selects data from combobox. I want it to appear on the Employee Form that is already opened..
EDIT:
Employee Form
namespace Master
{
public partial class Employee : Form
{
public Employee()
{
InitializeComponent();
searchForm.ItemSelected += ItemSelected;
}
private SearchForm searchForm = new SearchForm();
private void ItemSelected(object sender, ItemSelectedEventArgs e)
{
txtName.Text = e.SelectedItem.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
SearchForm searchForm = new SearchForm();
searchForm.Show();
}
}
}
Search Form
namespace Master
{
public partial class SearchForm : Form
{
public SearchForm()
{
InitializeComponent();
}
private void SearchForm_Load(object sender, EventArgs e)
{
}
private void cbFind_SelectedValueChanged(object sender, EventArgs e)
{
if (cbFind.SelectedItem != null)
{
if(ItemSelected != null)
ItemSelected(this, new ItemSelectedEventArgs(cbFind.SelectedItem));
}
}
public delegate void ItemSelectedEventHandler(object sender, ItemSelectedEventArgs e);
public event ItemSelectedEventHandler ItemSelected;
}
public class ItemSelectedEventArgs : EventArgs
{
public object SelectedItem { get; set; }
public ItemSelectedEventArgs(object selectedItem)
{
SelectedItem = selectedItem;
}
}
}
There are many many ways to achieve what you want, the most favorite I like is using some kind of event, yes event is one of the most interesting things in modern programming languages like C# (in .NET environment). However you can choose another solution simply like this:
//in your Search form
public string ShowSearch(){
if(ShowDialog() == DialogResult.OK){
return cbFind.SelectedItem == null ? "" : cbFind.SelectedItem.ToString();
}
return "";
}
//returning "" means some kind of cancel action which will result no search performed.
Search form should be one element in your Employee form, you can show your search form using the method above and get the returned selected item value.
That's not a decent way in some cases, here I introduce you the way using event, you have to declare some event to notify the selecting from user and show the selected item on your Employee form:
//your Employee form
public class Employee : Form {
public Employee(){
InitializeComponent();
searchForm.ItemSelected += ItemSelected;
}
//Search form
private SearchForm searchForm = new SearchForm();
//your ItemSelected handler
private void ItemSelected(object sender, ItemSelectedEventArgs e){
txtName.Text = e.SelectedItem.ToString();
}
}
//your Search form
public class SearchForm : Form {
public SearchForm(){
InitializeComponent();
}
//handler for your combobox SelectedValueChanged event.
private void cbFind_SelectedValueChanged(object sender, EventArgs e)
{
if (cbFind.SelectedItem != null)
{
if(ItemSelected != null) ItemSelected(this, new ItemSelectedEventArgs(cbFind.SelectedItem);
}
}
public delegate void ItemSelectedEventHandler(object sender, ItemSelectedEventArgs e);
//your own event
public event ItemSelectedEventHandler ItemSelected;
}
public class ItemSelectedEventArgs : EventArgs {
public object SelectedItem {get;set;}
public ItemSelectedEventArgs(object selectedItem){
SelectedItem = selectedItem;
}
}
You can use traditional ways which pass values between classes... but I recommend using event (as the code above shows) or at least some kind of delegate. Programming in .NET environment requires you to make familiar with events and delegates much more...
on your parent form you should do this
private void button1_Click(object sender, EventArgs e)
{
Form1 searchForm = new Form1();
if (searchForm.ShowDialog() == DialogResult.OK)
{
string selectedRecord = searchForm.SelectedRecord;
}
}
where button1 is your button to open the search form. Form1 is your search form. and selectedRecord is your property that you set before closing the search form. I have assumed that it is a string though it can be any object.

How to add row to datagridview situated on another form

i have two form applictaion. and i have datagrid with three string columns on the "MainForm".
the destination of the second form is to add rows to this datagrid with some parametres such as text of the 1,2 and 3 columnns
this code works
private void MainForm_Load(object sender, EventArgs e)
{
dgvTasks.Rows.Add("s1", "s2", "s3");
}
but when i drop this code to another form it doesn't work
//"MainForm"
public void addRowToDataGridView(string type, string title, string time)
{
dgvTasks.Rows.Add(type, title, time);
}
//"ParametersForm"
public static MainForm fm = new MainForm();
private void btnSave_Click(object sender, EventArgs e)
{
fm.addRowToDataGridView("s1", "s2", "s3");
}
no errors. just silent and rows don't add.
can smb help me?
MainForm fm = new MainForm();
This way , You created another MainForm when you create instance object for MainForm.
You should attain active MainForm. So you should hold the active MainForm instance.
//"MainForm"
public static MainForm MainFormRef { get; private set; }
public Form1()
{
InitializeComponent();
MainFormRef = this;
}
public void addRowToDataGridView(string type, string title, string time)
{
dgvTasks.Rows.Add(type, title, time);
}
//"ParametersForm"
private void btnSave_Click(object sender, EventArgs e)
{
var fm = MainForm.MainFormRef;
fm.addRowToDataGridView("s1", "s2", "s3");
}
As I understand your question, i can suggest you such an answer
Make a property 'setter' in MainForm of any type
(Ex: a
//here is your MainForm
{
public List<MyGVContent> SetColumnHead
{
set
{
//here call your method to whom give 'value' as parameter
//attention, that in value contains items with Type, Title, Time
addRowToDataGridView();
}
}
//which will update your 'dgvTasks' gridview
)
//here is your Parameters Form
{
private void btnSave_Click(object sender, EventArgs e)
{
//here call the property to whom send parameters
this.MainForm.SetColumnHead = ...
}
}
//where
public sealed class MyGVContent
{
string Type
{
get; set;
}
string Title
{
get; set;
}
string Time
{
get; set;
}
}
Good luck.

Categories