How do i transfer control information between windows - c#

I wanted to know how do i transfer multiple information between windows in WPF.
So far I have this:
Main form:
string path = #"C:\";
private void preview_Click(object sender, RoutedEventArgs e) {
preview newWindow = new preview(Path);
newWindow.Show();
}
The preview form:
public preview(string _path) {
InitializeComponent();
Path = _path;
}
But this only allows me to send one piece of information at a time. How would I send multiple information at one time?

Well, if you're sticking to that particular design, then you can send information in a class or a struct, which you would pass instead of the string:
preview newWindow = new preview(data);
public preview(CustomData data) { ... }
Or just pass multiple arguments if your constructor accepts multiple parameters:
preview newWindow = new preview(path, somethingElse, somethingMore);
public preview(string path, int somethingElse, int somethingMore) { ... }
I just prefer to keep things nice and tight if I work with some sort of collection of data a lot, that's why I recommended class or struct. However, if pieces of information have no particular relation to each other beyond being passed together, then multiple parameters approach works just fine.

You can pass your three values in a three parameter constructor of preview class.
string path = #"C:\";
private void preview_Click(object sender, RoutedEventArgs e) {
preview newWindow = new preview(1,"string1","String2");
newWindow.Show();
}
The preview form:
int a;
string b;
string c;
public preview(int _a, string _b, string _c)
{
InitializeComponent();
this.a=_a;
this.b=_b;
this.c=_c;
}
If you have to pass more values to Preview form I would suggest you should create a DTO class that will contain all the values you want to pass to preview form. Create instance of DTO class on your mainform and set values as required and pass this DTO class to preview form and on preview form you can have a custructor that will accept this dto class.

Related

Is there a way to pass the DbSet<T> into the page?

I have the window with the page. The page displays a data from the my database. Also, on the window the buttons are placed, whose contents is according to the tables names of the database. These buttons switchs the page's content.
For example, this is the btnUsers button's click event, which displays the "Users" table:
void btnUsers_Click(object sender, RoutedEventArgs e) {
this.FrameMain.Navigate(new pageTable(Context.ctx.Users, ...));
}
The pageTable is the my "generic" page, that receives the Users class. Here is its constructor, which doesn't works:
public pageTable(dynamic table, ...) {
InitializeComponent();
TableTemplate<dynamic>.Init(table, ...);
}
Here is the my generic class, that operates on the DbSet<T>:
static class TableTemplate<T> {
internal static void Init(T table) {
foreach (string f in Foo(table, ...) {
...
}
}
}
The Foo method just extracts the columns from the DbSet<T> table:
internal static string Foo<T>(T item, ...) {
...
}
The point is, that the application terminates when I try to get the data from the table, at the button's event, used this generic approach.
I noticed, that at the Foo method, during the debug, the T type is differs, depending on the way, with which I pass the DbSet<T>:
if I explicitly initialize a new class instance (for the test):
static class TableTemplate<T> {
internal static void Init(T table) {
foreach (string f in Foo(new Users(), ...) {
...
}
}
}
, then the T type is System.Data.Entity.DynamicProxies.Users_E006B3..., and the Foo method is works;
without the explicitly initialization the T type is System.Data.Entity.DbSet`1[Namespace.Users], and the Foo method isn't works.
Is there a possibility to pass the generic entity class into the page? I don't know if XAML has a generic classes support, to use the generic pageTable<T> page. It could be a solution, but I suppose there is a more neat way to pass the entity.
I found the solution, and it doesn't use the generic page.
Well, when I tried to print the table content, I discovered, that pass a structured query into the TableTemplate.Init(). I remember, that never used the dbContext.TableClass as a function argument before, always converting the TableClass into the list.
I confess, I don't understand the EntityFramework and didn't expect such a result. Generally, I used the object type and already forgot why used the dynamic type...
I decided to pass the DbSet<T>, converted to the list (and this, as I understand it, are the different thigns) into the page's constructor, instead of the DbSet<T>. But, because I doesn't use the general page, I converted the items of this list into the object:
void btnUsers_Click(object sender, RoutedEventArgs e) {
this.FrameMain.Navigate(new pageTable(Context.ctx.Users.ToList<object>()));
}
Now, the pageTable page's constructor is next:
public pageTable(List<object> table) {
InitializeComponent();
TableTemplate<object>.Init(table, ...);
}
And, the Init method of the TableTemplate class is next:
internal static void Init(List<T> tableList) {
if (tableList.Count > 0) {
foreach (string f in Foo(tableList[0], ...) {
...
}
}
}
I haven't figured out how to display only the table's columns names, if tableList is empty. Thus, in this case, for now the page displays the empty DataGrid without the columns names. Nevertheless, I am glad, that could do I wanted.
At last, I will say, that indirectly agree with Xerillio.

Public variable invoking incorrect result

public partial class ThanglishToTamilGUI : Form
{
public string anz;
public ThanglishToTamilGUI()
{
InitializeComponent();
}
public void btnConvertToBraille_Click(object sender, EventArgs e)
{
anz = richTextBoxTamil.Text.ToString();
GUI.TamilToBrailleGUI c1 = new GUI.TamilToBrailleGUI();
c1.Visible = true;
}
}
I need to pass my richtextbox (richTextBoxTamil) content to variable call anz.
I am retrriving anz variable in other form as form load event:
private void TamilToBrailleGUI_Load(object sender, EventArgs e)
{
ThanglishToTamilGUI tt = new ThanglishToTamilGUI();
String apper = tt.anz;
richTextBoxTamil.Text = apper;
}
My Problem:
I am getting null values as result. Since if I assigned any values that invoked correctly.
public partial class ThanglishToTamilGUI : Form
{
public string anz = "Hai";
public ThanglishToTamilGUI()
{
InitializeComponent();
} ...
Here my ans value is passed as "Hai". But my requirement is to get what ever the content in the richTextBoxTamil and pass it to that public variable call anz. What went wrong here please help me.
Thank you.
This is the problem:
ThanglishToTamilGUI tt = new ThanglishToTamilGUI();
String apper = tt.anz;
How do you expect apper to ever be anything other than null? You're fetching the variable from a freshly-created form, which has never been shown, and which has never had btnConvertToBraille_Click called on it.
Presumably there's an existing ThanglishToTamilGUI object somewhere, and that's the one you want to fetch the variable from. Basically, one form needs to know about the instance of the other form.
(I'd also strongly suggest using a property rather than a public variable, but that's a different matter. You might not even need to have a separate variable at all - just declare a property which fetches richTextBoxTamil.Text.)
Alternatively, just pass the relevant string to the constructor of the new form:
public void btnConvertToBraille_Click(object sender, EventArgs e)
{
GUI.TamilToBrailleGUI c1 = new GUI.TamilToBrailleGUI(richTextBoxTamil.Text);
c1.Visible = true;
}
Then the new form doesn't need to know about the old form at all - it only needs to know the text to display.
(You might want to pull it out of the constructor and into a settable property, but it's the same basically principle: the code creating the form pushes the data, rather than the new form pulling it.)
You can create a public property to access the current Text value of the textbox.
public string RichTextBoxText
{
get
{
return richTextBoxTamil.Text;
}
}
The way you do it now the form is instantiated, but the click event is not fired. So there's no way you will get anything other than what you initialized the field to.
Load is not the place to look for user input. An event (like click) is where you need to check the property value:
private void SomeClick(object sender, EventArgs e)
{
String result = thanglishToTamilGUIObject.RichTextBoxText;
//do something with text
}

winforms - suggested class structure and clone (not by reference)

My program class has:
Application.Run(new Form1());
in form1 class I have:
model = new Model(this);
modelarray myArray = new modelarray(this);
model = myArray.models[0];
myArray.models[1] = (Model) model.Clone();
private void btn13_Click(object sender, EventArgs e)
{
model.btn13Clicked();
}
private void btnGetBackClone_Click(object sender, EventArgs e)
{
model = myArray.models[1];
//here I'm expecting to get the original object back (ie. with btns[7,7].Visible = True) but it doesn't work!!
}
in model class I have:
private Button[,] btns;
public Model(Form1 form1)
{
btns = new Button[10,10];
myform = form1;
btns[8, 6] = form1.btn1;
btns[9, 5] = form1.btn2;
btns[7, 7] = form1.btn13;
}
public void btn13Clicked()
{
btns[7, 7].Visible = False;
}
public object Clone()
{
return this.MemberwiseClone();
}
in modelarray class I have:
public Model[] models = new Model[19];
public modelarray(Form1 form1)
{
models[0] = new Model(form1);
}
Note my comment under the btnGetBackClone_Click method.
"//here I'm expecting to get the original object back (ie. with btns[7,7].Visible = True) but it doesn't work!!"
I understand that this is because models[0] and models[1] are pointing to the same memory location (ie copy by ref). But I am really lost at how to implement a solution in this situation. Searches on 'deep copy' did not seem to help as serializing a form didn't work. Can someone please correct my cloning error?
I know I could simply redo "btns[7, 7].Visible = True;" but I would like to know a cloning solution so it will copy all future fields I decide to put in my model.
I've had a search on codeproject.etc but there doesn't seem to be any straightforward intro to winforms.
.NET usually uses shallow copies during Clone operations.
In order to implement deep copies, you typically have 2 options
Serialize / deserialize (if your classes are all serializable) - e.g. Here
By using reflection e.g. Here
If you split your data (model) concerns out of your form (view), you can then more easily 'clone' just the data.

Can I add controls to the C# MessageBox?

Could I add some custom control to the standard Message Box for read input value, for example text fields for user name and password, or I should create custom winform with "Ok,Cancel" buttons and text fields?
Related: Which control to use for quick text input (inputbox)?
you can use the Interaction.InputBox method wich is located in the Microsoft.VisualBasic namespace
try this
Microsoft.VisualBasic.Interaction.InputBox("Enter a Value Here", "Title", "Your Default Text",200,100);
You will need to create a custom WinForm to do this. You can make it work the same way as a MessageBox by returning a DialogResult on the Show method.
Create your own.
Creating a custom modal (or otherwise) input dialog isn't all that difficult and you can built the extensibility you need for reuse.
public class ValueHolder {
public string SomeInput { get; set; }
public DialogResult Result { get; set; }
}
public class GimmeValues : Form {
//... HAS A TEXTBOX and Okay Buttons...
private GimmeValues() {
okButton.DialogResult = DialogResult.OK;
cancelButton.DialogResult = DialogResult.Cancel;
// ... other stuff
}
public static ValueHolder GetInput(IWin32Window owner) {
using (GimmeValues values = new GimmeValues()) {
DialogResult result = values.ShowDialog(owner);
return new ValueHolder {
SomeInput = values.Textbox1.Text,
Result = result
};
}
}
}
Okay I just wrote that all in this editor so forgive any syntax mistakes.
You could do something like the above but clean it up a little, add the extensibility you need (in terms of buttons and inputs showing that you need etc)... then just call it like ValueHolder value = GimmeValues.GetInput(this); where this would represent an IWin32Window...
The resulting value of value would be the selected nonsense and you could perform your logic..
if(value.Result == DialogResult.OK && !string.IsNullOrEmpty(value.SomeInput)){
//TODO: Place logic....
}
You'll have to create a custom form to handle that.
If you want the Form to behave like MessageBox, just create a static Show() method on your Form that creates an instance and shows the box to the user. That static method can also handle returning the values you are interested in from your custom form (much like DialogResult).

WinForms - Baffled - How to Handle Certain Controls Dynamically - Properly

I have a System.Windows.Form class (my main class). There is a RootMenu object. This is my own custom object. I'm trying to loop through the RootMenu object and on each pass add a ToolStripMenuItem to a ContextMenuStrip (which I named ContextMenu). The RootMenu object contains a List. Links have Names and Urls (both strings).
When the form loads my "Factory" class loads me up a RootMenu object, which I then pass into the ProcessMenu method.
Code Excerpt Here:
private void ProcessMenu(RootMenu rm)
{
foreach (var lnk in rm.Links)
{
var tsmi = new ToolStripMenuItem(lnk.Name, null, new EventHandler(Navigate));
tsmi.ToolTipText = lnk.Url;
ContextMenu.Items.Add(tsmi);
}
}
private void Navigate(object sender, EventArgs e)
{
var tsmi = (ToolStripMenuItem) sender;
System.Diagnostics.Process.Start(tsmi.ToolTipText);
}
Do you see how I have to store the lnk.Url in the ToolTipText? In the VB6 days all the controls had the "tag" property. You used to be able to stuff extra stuff into the control that you would need later on. I don't want to use the tooltip for this, but what are my alternatives? Storing all the Urls in a Hash/Dictionary using the name as a key? I may not always have unique names, so I would like to avoid this route. What is the proper way to handle this in .NET? Maybe I missing some basic concept I have never been exposed to.
ToolStripMenuItem has a Tag property:
tsmi.Tag = lnk.Url;
In fact, quite a few Windows Forms controls have it.
Just inherit the old class and stick a Tag property in there:
public class myToolStripMenuItem : ToolStripMenuItem
{
public object myTag { get; set; }
}
Create your own object inheriting from ToolStripMenuItem and add any custom properties....
private void ProcessMenu(RootMenu rm)
{
foreach (var lnk in rm.Links)
{
var tsmi = new UrlToolStripMenuItem(lnk.Name, null, new EventHandler(Navigate))
{
Url = lnk.Url,
};
ContextMenu.Items.Add(tsmi);
}
}
private void Navigate(object sender, EventArgs e)
{
var tsmi = (UrlToolStripMenuItem)sender;
System.Diagnostics.Process.Start(tsmi.Url);
}
public class UrlToolStripMenuItem : ToolStripMenuItem
{
public UrlToolStripMenuItem(string text, Image image, EventHandler onClick) : base(text, image, onClick)
{
}
public string Url { get; set; }
}

Categories