I am working on C# wpf, and I am trying to create 'favorite' function on it.
There is one window called 'favorite' and it is where a user can save his data.
Another window is 'MainWindow' and I want to load the data here.
There are two buttons and two textbox in 'favorite'.
If I type words in each box, I hope they can be saved if I click star1button.
And if I type another words in each box, I hope they would be saved if I click star2button.
So I hope each data will be stored separately, without being overlapped.
And then, if I press button1 on 'mainwindow', I hope those words of star1button would show up in textboxes of mainwindow.
And if I press button2 on mainwindow, I hope words of star2button would show up in textboxes of mainwindow.
Thanks in advance!!
You can place an attribute in your App.xaml.cs which should be accessible from both
namespace MyApp
{
sealed partial class App : Application
{
public string myValue;
// the rest of your App.xaml.cs code
}
}
Then in your MainWindow and other window put this code
public string MyValue
{
get
{
return (Application.Current as MyApp.App).myValue;
}
set
{
(Application.Current as MyApp.App).myValue= value;
}
}
You can use a static class to pass values between windows.
public static class CurrentParameters
{
public static string mySharedValue { get; set; }
}
Related
I have the following static method that adds a selected product into an order.
public static void addToOrderFromPicture(string product, string qty, string _price)
{
//I've cut the code as it's not important to the question.
order.Add(product);
}
The products are displayed as Controls on a flow layout panel. The user will click the 'Add to Order' button on the control. This activates the following method.
private void btn_add_Click(object sender, EventArgs e)
{
if (Main.sessionInProgress == true)
{
OrderQty qty = new OrderQty(lbl_caseSize.Text.ToString(), lbl_wholesale.Text.ToString(), lbl_product.Text, lbl_volume.Text.ToString(), lbl_physical.Text, lbl_available.Text, lbl_oo.Text, lbl_inner.Text, lbl_pltQty.Text, lbl_repeat.Text);
qty.StartPosition = FormStartPosition.CenterParent;
DialogResult result = qty.ShowDialog();
if (result == DialogResult.Yes)
{
if (Main.roundCheck == true)
{
// MessageBox.Show(qty.qtyReturn.ToString());
qty.qtyReturn = autoRoundToCaseSize(qty.qtyReturn);
//MessageBox.Show(qty.qtyReturn.ToString());
Main.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
}
else
{
Main.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
}
btn_add.Text = "X";
btn_add.BackColor = Color.FromArgb(236, 112, 99);
}
}
}
The reason for the main function being static is so I can call it from this method. In Swift I would use a delegate to pass data between forms etc. However, I'm unsure on how to do this within C#.
Is there a similar method for passing data between forms as there is in Swift. How would I go about doing it? Or is there a way for me to call the method in Main without the need for it to be static.
EDIT: I don't think I've explained the forms etc very well so will try clear it up.
The addToOrderFromPicture method is contained within Main. This function adds products to the order list which is also static and contained within Main.
The 'btn_add_Click' method is contained in Product.cs which is a UserControl. This user control is displayed on a flowPanel which sits on the main form.
So the user clicks activates a function on Product.cs, this creates an instance of OrderQty.cs which is returns a qty to Product.cs - From Product.cs the addToOrder method within Main is called and the data like qty etc is passed to it.
So Product.cs -> OrderQty.cs -> Product.cs -> Main.cs
Your form is still accessible after you've called this.Close() and ShowDialog has returned, so you can do this:
OrderQty qty = new OrderQty(lbl_caseSize.Text.ToString(), lbl_wholesale.Text.ToString(), lbl_product.Text, lbl_volume.Text.ToString(), lbl_physical.Text, lbl_available.Text, lbl_oo.Text, lbl_inner.Text, lbl_pltQty.Text, lbl_repeat.Text);
qty.StartPosition = FormStartPosition.CenterParent;
DialogResult result = qty.ShowDialog();
if (result == DialogResult.Yes)
{
qty.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
}
Maybe you can keep your logic in a separate class instead of Main.
public class Service
{
public List<Product> Order { get; set; }
public void addToOrderFromPicture(string product, string qty, string _price)
{
Order.Add(product);
}
}
3 methods to do this.
First as the main window is created once use singleton pattern on it, declare a public static instance of form and access public methods,
Second pass a reference of main window to usercontrol and use its public methods.
Third add an event to usercontrol and hook handler in main window, whenever user clicks button, fire an event.
I'm looking to do something very simple (or what I perceive as simple).
Basically, I have two pages set up in my XAML/C# UWP app, the first has a series of textboxes and dropdown menus to select options (Name, State, etc).
On the bottom there is a button to go to the next page.
On the next page, I would like to be able to display the user entered data.
I'm trying to figure out the best way to do this, but after hours of searching, I can't seem to figure out how to pass multiple values between pages. I think I want to create a Class file that stores all of this info, but I'm not exactly sure how to set the values in the C# code from the first page and get the info on the second page.
UPDATE:
So using the answer below I've gotten here:
On the MainPage
public sealed partial class MainPage : Page
{
public static MainPage Current;
public static string PageOneSelection
{
get; set;
}
public void changeToNextPage()
{
PageToLoad.Navigate(typeof(TwoPlayerGame));
}
public MainPage()
{
this.InitializeComponent();
Current = this;
PageToLoad.Navigate(typeof(Selection));
}
}
}
And on the Selection Page:
public sealed partial class Selection : Page
{
new string Name;
public Selection()
{
this.InitializeComponent();
}
private void PlayButton(object sender, TappedRoutedEventArgs e)
{
MainPage.Current.PageOneSelection = PlayerOneName.Text;
MainPage.Current.changeToNextPage();
}
}
}
You should have a MainPage which holds all of your pages in Frames.
<Page x:Name="Main">
<Frame x:Name="PageToLoad">
</Page>
On the MainPage you have a global which holds "this" and globals to store your selection values from the various pages.
public static MainPage Current;
public static string PageOneSelection;
And functions to get/store your selections:
public string getPageOneSelection()
{
return PageOneSelection;
}
public void setPageOneSelection(string whatToSetItTo)
{
PageOneSelection=whatToSetItTo;
}
On Initialization
// This is a static public property that allows downstream pages to get a handle to the MainPage instance
// in order to call methods that are in this class.
Current = this;
On Initialize of the MainPage you should load the first page:
PageToLoad.Navigate(/*Your First Page*/);
Now whenever they make a selection you can call back and forth to the MainPage to change that selection value
//On Page 1
MainPage.Current.setPageOneSelection(theSelectedItem);
//On Page 2
itemFromPage1=MainPage.Current.getPageOneSelection();
UPDATE: Your code looks good. So you say you have a textbox you want the information for. You can do this:
MainPage.Current.setPageOneSelection(textbox.Text);
I'd put this before you navigate to the next frame.
If you have a second selection (ie your dropdown), make another global on your MainPage and do the same thing.
Also if you have can send more than one string at a time, add parameters to your set function:
public void setAllPageOneSelections(string param1, string param2 /.../)
{
PageOneSelection=param1;
PageOneSelection2=param2;
}
In your Main you should probably have a page switcher function. I use:
public void changeToNextPage()
{
PageToLoad.Navigate(/*Page 2 or next page or something */);
}
and then for your play button you can do
MainPage.Current.changeToNextPage();
use this :-
define this variable:-
publicstatic mytextboxinfo {get;set;}
and in your function :-
submitbutton_Click(){
mytextboxinfo = mytextbox.text;
}
and then in the next page :-
Page_loaded() {
mytextbox2.Text = myPage.mytextboxinfo;
}
where "myPage" is the name of the page
I got four windows.
Window1 has Textboxes and radiobuttons.
Basing on window1 , window2 opens.
basing on window2 , window 3 opens.
and window4 opens on basis of window1 information but the button is on window3 which opens window4.
what i am trying to do is to send window1 information to window3 so that i can open window4.
but i am unable to do it.
i know how to pass values from one form to the second one. but this is complex and i tried it.
I have even tried the following link as well please enlighten me with the answer.
https://www.daniweb.com/software-development/csharp/threads/370098/hold-a-text-box-string-to-another-window-form
Window2 opening Code:
if ((SeismicLevel_TextBox.Text == "Low") && (LevelOfPerformance_LS_RadioButton.IsChecked == true))
{
Region_of_Low_Seismicity t1_1 = new Region_of_Low_Seismicity();
t1_1.ShowDialog();
}
Window 3:
Window3 w3 = new Window3();
s.ShowDialog();
Window 4 but the button lies on window 3:
if ((w1.SeismicLevel_TextBox.Text == "Low") && (w1.LevelOfPerformance_LS_RadioButton.IsChecked == true))
{
Window4 W4 = new Window4();
W4.ShowDialog();
}
Ideally, you would want to create a ViewModel for each Window, and then inject Window1's ViewModel into the other three via Dependency Injection. Though, for the sake of getting this working (and assuming you are not familiar with MVVM concepts yet), you can simply do the following:
As shown below, just create a POCO that is passed into the constructor of Window3 upon opening. The POCO will be populated with the control values from Window1. You will need to update the constructor for Window3, but it's as simple as adding an new parameter to its constructor.
// POCO to store Window1 info
public class Window1Values
{
public string TextBoxValue1 { get; set; }
public bool CheckBoxValue1 { get; set; }
}
// Update Window 3 Ctor to look like the following, simply just add a parameter to the existing Ctor
//
public Window3(Window1Values window1Values)
{
// ...
}
// When Window 3 is going to open, do the following
//
var w3 = new Window3(new Window1Values
{
TextBoxValue1 = myTextBox.Text;
CheckBoxValue1 = myCheckBox.IsChecked;
});
w3.ShowDialog();
I would pass parameters through the pages.
For example, I'm a bit rusty but you should call a navigator to PageName(). So, pass arguments like PageName(ButtonVal, Text) and give PageName() a constructor accepting everything passed to it, and everything subsequent pages need.
Parameters would be a good idea, but it could get messy having to pass the same data through multiple windows. Instead an option could be to create a "Storage" class which you can save data to and access later on in the program.
public class Storage
{
public static string textBoxValue1 { get; set; }
public static bool checkBoxValue1 { get; set; }
}
The data binding works as it I intend, kind of... The real issue I'm running into now is what I believe to be 2 different instances of my User Control, but only the original, debug list I implemented is showing.
In short, I am building 2 lists that are technically bound to the data grid, the default debugging list I created in the default constructor and then the real list I created to bind to the data grid.
Every time I click on the user control with the data grid, the default constructor adds another line to my debugging list and displays it on the screen.
Every time I click the button that builds a list of selected options on a separate user control I can see my the options add on to the list of options I had been creating and technically set it to the data context of the data grid, the same way the default debug list does, except when I click back over to the data grid user control, the default constructor runs again, ads another line to my debug list, and displays the debug list that is being built.
Here's a copy of the class with a couple lines I added to help debug the problem.
public partial class QuotePreview : UserControl
{
private SelectionList _selectionList;
private SelectionList temp;
public QuotePreview()
{
InitializeComponent();
_selectionList = (SelectionList)this.DataContext;
}
private void QuotePreview_Loaded(object sender, RoutedEventArgs e)
{
//Adds item to Debugging list
_selectionList.SelectedOptions.Add(
new Selection
{
ModelNumber = "this",
Description = "really",
Price = "sucks"
});
}
public QuotePreview(SelectionList selectedOptions)
{
InitializeComponent();
_selectionList = (SelectionList)this.DataContext;
temp = selectedOptions;
//The list I am actually trying to display
_selectionList.AddRange(selectedOptions);
QuotePreview_Loaded();
}
private void QuotePreview_Loaded()
{
foreach (var options in temp.SelectedOptions)
{
_selectionList.SelectedOptions.Add(options);
}
QuotePreviewDataGrid.ItemsSource = _selectionList.SelectedOptions;
}
}
The implementation of the default constructor, is called every time the user control / tab, is clicked on. When that happens, _selectionList is set to the data context of the user control, followed by the Loaded Event which adds a line to my data grid.
In another user control where I select the options I want to add to my data grid user control, I click a button that creates a list of the options I want to be added and calls the custom constructor I wrote. Once the constructor finishes, it calls a custom Loaded Event method that I created for shits and giggles, that adds the selected options to my _selectionList.
Now once I click on the data grid user control again, it goes through the whole default process, and adds another default line.
If I go back a tab and say I want these options again and go back to the data grid, it again goes through the default process and adds another default line.
Whats most intriguing though is that I can see both of the selectionLists build since I dont clear the in between processes. I see a list build of the options i want to display and a list build of the default options build...
Oh, also, SelectionList does implement ObservableCollection
i don't follow exactly what you are asking but loaded event will fire whenever load is required and in your case you are switching between the views , TabControl will not render its content until it is required !
bool _isDefaultItemAdded = false
private void QuotePreview_Loaded(object sender, RoutedEventArgs e)
{
if(!_isDefaultItemAdded)
{
//Adds item to Debugging list
_selectionList.SelectedOptions.Add(
new Selection
{
ModelNumber = "this",
Description = "really",
Price = "sucks"
});
_isDefaultItemAdded = true;
}
}
I finally came up with a solution to the problem.
public static class QuotePreview
{
public static ObservableCollection<PurchasableItem> LineItems { get; private set; }
static QuotePreview()
{
LineItems = new ObservableCollection<PurchasableItem>();
}
public static void Add(List<PurchasableItems> selections)
{
foreach (var selection in selections)
{
LineItems.Add(selection);
}
}
public static void Clear()
{
LineItems.Clear();
}
}
public class QuoteTab : TabItem
{
public ObservableCollection<PurchasableItem> PreviewItems { get; private set; }
public QuoteTab()
{
Initialize()
PreviewItems = QuotePreview.LineItems;
DataGrid.ItemSource = PreviewItems
}
}
I am attempting to implement a model view presenter pattern in C# windows forms. I have tried several different methods but have not figured this out. Is there anyway to "accept" user input from a text box when the user clicks off of the text box? If there is not, what is the typical way to pass data to the presenter? I can use the textbox's on_text_changed event but then I am confused on how to validate the data.
I think its easy here are the MSDN links that illustrate the function of TextBox class with code.
TextBoxBase.Text Property
& validate using:
Control.Validated Event
Hope it helps!
I know this thread is a way too old but still.
public interface IProjectView
{
string textBoxText{get;}
}
implement it in ProjectView
public class ProjectView : IProjectView
{
ProjectPresenter _presenter;
public ProjectView()
{
_presenter = new ProjectPresenter(this);
}
string textBoxText
{
get
{
// Do validation if you want
return textBox1.Text;
}
}
}
class ProjectPresenter
{
IProjectView _view;
public ProjectPresenter(IProjectView view)
{
_view = view;
}
public void AnyMethod()
{
// Access value of textbox as _view.txtTextBoxText
}
}
Code not tested, but should work fine.
Regarding validation, while implementing the property in ProjectView, do the validation before returning value.
You'll want to listen for the Leave event. That'll happen when the textbox loses focus; after that, you can do your validation.