When I search this question, all of the answers I've seen only talk about handling an object within the same class but I need to handle the same data between classes.
I'm building an outlook addin which uses three classes to make up the key components of my programme:
ThisAddin - the default class created with the MS VS template, I'm using this class to store all of my methods, enums, data stores etc..
Ribbon - my outlook Ribbon containing a button to initiate a new enquiry form. Within the button_click is also a code to save relevant attachments from a selected email to a specified filepath.
NewEntry - a winform dialogue initiated when the ribbon button is clicked, used to create new enquiries.
I also have a class called NewSearchQuery which I was hoping to use as a datastore for all the relevant aspects of a new enquiry.
current logic goes like this - user presses button in the ribbon, a new object (referenced as Temp) is called and known data for some parameters are filled. Winform is opened and user fills in some more required data. On form submit, that data is added to the object metadata, a reference number is generated from a database, a file path is created using the reference number and all this is again added to the object metadata. Winform dialog closes and the ribbon saves the selected email attachments to the specified filepath stored within the object. Now all the object metadata can be sent to the enquiry database as a new enquiry.
Here's the code:
public enum ContractType
{
Searches, //there are other values in my code but they don't need to feature here
}
public class NewSearchQuery
{
public string Name, Location, SearchType, Path;
public int RefNum;
public bool Paid;
public ContractType Contract;
}
public partial class Ribbon
{
private void button1_Click(object sender, RibbonControlEventArgs e)
{
NewSearchQuery Temp = new NewSearchQuery();
Temp.Contract = ContractType.Searches;
var NewEntry = new NewEntry(Convert.ToString(Temp.Contract));
NewEntry.ShowDialog();
//wait until the NewEntry Dialogue and associated methods close and then run the below save attachments method:
var m = e.Control.Context as Inspector;
var mailitem = m.CurrentItem as MailItem;
mailitem.SaveAs(Temp.Path + #"\Initial_Contact.msg");
if (mailitem != null)
{
if (mailitem.Attachments.Count > 0)
{
foreach (Attachment item in mailitem.Attachments)
{
string[] extensionsArray = { ".jpg", ".jpeg", ".gif", ".png", ".tiff", ".tif", ".eps", ".bmp", ".vcf" };
if (!extensionsArray.Any(item.FileName.Contains))
{
item.SaveAsFile(Path.Combine(Temp.Path, item.FileName));
}
}
}
else
{
MessageBox.Show($"Operation Complete. Enquiry number {Temp.RefNum}. This email doesn't have any attachments.");
}
}
MessageBox.Show($"Operation Complete, Enquiry number {Temp.RefNum}.");
}
}
public partial class NewEntry : Form
{
public NewEntry(string ContractType)
{
InitializeComponent();
}
private void Create_Click(object sender, EventArgs e)
{
//here are the variables I would like to tie into the Temp object created in Ribbon
Temp.Name = Convert.ToString(Companies.SelectedItem);
Temp.Location = Convert.ToString(SearchLocation.Text);
Temp.SearchType = Convert.ToString(Search.SelectedItem);
Temp.Paid = Paid.Checked;
if (Temp.Name == "" || Location == "" || SearchType == "")
{
MessageBox.Show("Please ensure you have filled in all the required fields (*) before proceeding", "ERROR: insufficient info");
}
else
{
Temp.RefNum = ThisAddIn.FindIdNum();
Temp.Path = ThisAddIn.CreateFilePath(Temp.RefNum);
MessageBox.Show(Convert.ToString(d));
this.Close();
}
}
}
How can I reference the same object from both the Ribbon and NewEntry classes to keep all my required data centralised?
It looks like you don't need to actually share and you only want NewEntry to give you a NewSearchQuery when it completes.
That is pretty easy just add a method on NewEntry like this:
public NewSearchQuery GetEntry()
{
// make a new NewSearchQuery
var q = new NewSearchQuery();
// set its values from the form eg
q.Name = Convert.ToString(Companies.SelectedItem);
return q;
}
Then in the ribbon just do this after the ShowDialog:
var q = NewEntry.GetEntry();
So the idea is that the NewSearchQuery is always created by the form.
If you want a 2 way thing, create the NewSearchQuery first, then pass to the form using a similar method that initializes the form from the values.
Related
I have a C# very big C# application with a lot of values that are saved in a JSON file. At the very start, I can either do it fresh (i.e: choose new values as I enter in the values in the textboxes etc) or load an existing JSON file. There are no problems with either of that.
However, now what I want to be able to do is that if I load in an existing JSON file with said values, and if I go back then those values should be cleared up. Let me demonstrate all this more with examples.
So I have two modes- fresh and update. In fresh, I type in those values manually however in update, you are asked to upload a JSON file and then those values are loaded in their respective text boxes, check boxes etc.
As it stands now, if I have loaded in a JSON file and then I click "Back" to go to fresh mode, the values are not reset and my application loads in the values from the JSON file. I want to be able to clear those values and reset them. I don't know how to achieve this.
In the "browse" button where the user loads up the JSON file, I have this code:
private void Browse_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog
{
DefaultExt = ".json",
Filter = "JSON Files (*.json)|*.json"
};
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
Configs.ConfigPath = dlg.FileName;
jsonFile.Text = dlg.FileName;
string userJson = File.ReadAllText(Configs.ConfigPath);
try
{
var json = JsonConvert.DeserializeObject<AppConfigs>(userJson);
try
{
CopyNotNulls(json, Configs.Default);
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
}
For the xaml of the text box where you load in the json file, I have this TextChanged event arg and if I manually remove what the user has loaded and delete the text in that text box, then that works fine. But I want it done so that whenever I go back from that page, it resets when I go back from the update page to fresh page.
If I understand the process of your application correctly you are loading the json file into an objet and the controls that display the data are bound to the object properties, right? the only thing you have to do to get rid of those values is to get a new object if you go the fresh route. Just do:
var json = new AppConfigs();
alternatively, if you want to keep some of the values you'd have to reset them, for example on the AppConfigs object you can add a public method that clears the fields you want to get rid of. That would look like this:
public class AppConfigs
{
public string stringProp { get; set; }
public bool boolProp { get; set; }
public int intProp { get; set; }
public AppConfigs()
{
// default values here
// or just call Clear();
stringProp = "";
boolProp = false;
intProp = 0;
}
public void Clear()
{
stringProp = "";
boolProp = false;
intProp = 0;
}
}
then you could call it on your button click:
json.Clear();
I've read a lot of topics on this issue but I'm not finding an answer. I'm fairly new to this so please bear with me.
I'm trying to pass values from datagridview to a list. And then in a new class I want to make som methods accessing that list. Trouble is that when I pass the datagridview it returns it without content and values which means I can't do anything with it.
The code under ////TESTING//// works like I want. I create an instance of the specified list and it's counting the amount of rows properly, see screenshot.
public List<vertEl> getVertList = new List<vertEl>();
//Opens the file dialog and assigns file path to Textbox
OpenFileDialog browseButton = new OpenFileDialog();
private void browse_Click(object sender, EventArgs e)
{
browseButton.Filter = "Excel Files |*.xlsx;*.xls;*.xlsm;*.csv";
if (browseButton.ShowDialog() == DialogResult.OK)
{
//SOME CODE TO GET DATA FROM EXCEL AND SOME METHODS TO CALCULATE
//VALUES TO PASS TO THE TAB VERTIKALELEMENTER TAB IN MY DATAGRIDVIEW
//VERTIKALELEMENTER IS vertElementerDgv IN MY CODE
////TESTING////
GetVertElementasList TEST = new GetVertElementasList();
getVertList = TEST.vertList(vertElementerDgv);
MessageBox.Show(getVertList.Count.ToString());
}
else return;
}
I now want to do this in a seperate class and call a method from that class to do the same but when I try that with code underneath I do not get the same count as when I have the code in form1 (public partial class BridgeGeometry). It return count of 0. The method foo() is assigned to the button 1 in the form.
class GetKoord
{
public GetVertElementasList getList = new GetVertElementasList();
BridgGeometry obj = new BridgGeometry();
public void foo()
{
var TEST = getList.vertList(obj.vertElementerDgv);
//var TEST = obj.getVertList;
MessageBox.Show(TEST.Count.ToString());
}
}
I also tried to get the values directly from the datagridview but there's nothing in it when I access it from a class which is not the form1/BridgeGeometry class.
Form - screenshot
You could run a loop and store the information with selected rows into a public var with something like this:
string itemOne = dataGridView1.SelectedRows[0].Cells[1].Value + string.Empty;
string itemTwo= dataGridView1.SelectedRows[0].Cells[2].Value + string.Empty;
string itemThree = dgMasterGridBun.SelectedRows[0].Cells[3].Value + string.Empty;
Variables
public var varItemOne = itemOne;
public var varItemTwo = itemTwo;
public var varItemThree = itemThree;
Based on the link I managed to get this working. Probably not the best solution, but a working one. I tried to wrap my head around databinding, listbinding etc. but since the class with the input values are a messy one I gave that up for now. The datagriview input values are a little from lists and some from other datagridview.
MSDN-forum: Accessing Form1 controls from a different class
Explanations are given in the link so I'll just provide how I did it in my program.
If my GetKoord class are like this:
public class GetKoord
{
private BridgGeometry bridgeGeometry;
public GetKoord(BridgGeometry form1)
{
bridgeGeometry = form1;
}
public List<vertElementerParam> getListvertElementer(List<vertElementerParam> theList)
{
//var vertElementerDgv = bridgeGeometry.vertElementerDgv;
GetVertElementasList getVertElementasList = new GetVertElementasList();
List<vertElementerParam> MyDgvListList = new List<vertElementerParam>();
MyDgvListList = getVertElementasList.vertList(bridgeGeometry.vertElementerDgv);
//MessageBox.Show(MyDgvListList.Count.ToString());
theList = MyDgvListList;
return theList;
}
}
then I can get the list in Button1_Click like this, check the screenshot in the first post:
public List<vertElementerParam> getVertList = new List<vertElementerParam>();
private void button1_Click(object sender, EventArgs e)
{
GetKoord getKoord = new GetKoord(this);
List<vertElementerParam> testList = new List<vertElementerParam>();
testList = getKoord.getListvertElementer(getVertList);
MessageBox.Show(testList.Count.ToString());
}
How do I get specific opened form and change the value of specific property of the the form. I'm trying to cast Form to a specific form to change the values of that specific form.
I have multiple forms opened with dynamic name depending on the id
public UserChatFrm varUserChatFrm;
public void UserChatFrmOpener(string sendToEmpID)// function that will open multiple chat form depending n the senderid
{
if (Application.OpenForms["UserChatFrm" + sendToEmpID] == null)
{
varUserChatFrm = new UserChatFrm(sendToEmpID);
varUserChatFrm.Name = "UserChatFrm" + sendToEmpID;
varUserChatFrm.Tag = "UserChatFrm" + sendToEmpID;
varUserChatFrm.lblName.Text = sendToEmpID;
//varUserChatFrm.Text = sendToEmpID;
varUserChatFrm.MdiParent = Application.OpenForms["MainFrm"];
varUserChatFrm.Show();
}
varUserChatFrm.BringToFront();
}
Here are the opened forms
UserChatFrm UserChatFrm11 -> textbox1
UserChatFrm UserChatFrm12 -> textbox1 // I want to change the text of this
UserChatFrm UserChatFrm13 -> textbox1
UserlistFrm UserlistFrm ->listview
Here's my code to get that specific form
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm.Name == "UserChatFrm" + rdr["emp_sys_id"].ToString())// this is queried in the database to naming specific form sample "UserChatFrm11"
{
UserChatFrm varUsrchat = frm; // not working error which has missing cast?
varUsrchat.textbox1.text = "sample"; // I want to change the value of specific
// or something like this
Application.OpenForms["UserChatFrm" + "12"].chatbox1.text = "sample"; //not working
}
}
Could you point out what am I missing?
I don't like the way you try to update the form, you can find a different solutions for this approach, my ideal way is create Interface and implement it for each form that you want update it, then cast the form to interface and Update the form:
public interface IFormUpdator<TModel> where TModel : class
{
void UpdateForm(TModel model)
}
Then implement this interface for each class:
public Form UserChatFrm : IFormUpdator<string>
{
public void UpdateForm(string model)
{
this.textbox1.text = model;
}
.....
}
then do the same for all other form which you want to update them
And you can update the form like this:
Application.OpenForms.OfType<IFormUpdator<string>>()
.ForEach(frm => frm.Update("Sample"));
Okay so I'm adapting a C# program to an asp program and I have a main form which contains a list box and another which adds new information to the list box. I can fill in the 2nd form and hold values in Application["getData"]; but when I go to the other page I need to run the following code.
public void AddGig()
{
AddGigForm frm = new AddGigForm();
if (Application["getData"] != null)
{
Application["saveData"] = Application["getData"];
gigList.addGig(frm.GetData());
UpdateListbox();
}
I run into problems at gigList.addGig as it goes back to the method GetData() on the 2nd form. I just have no idea what else to use.
GetData method:
public GigOpportunity GetData()
{
Application["GetData"] = new GigOpportunity
(txtId.Text, gigDate.SelectedDate, txtVenue.Text, txtGenre.Text,
Convert.ToDouble(txtCost.Text), Convert.ToInt32(txtCapacity.Text), chkHeadliner.Checked, txtMainAct.Text, chkEngineer.Checked);
return new GigOpportunity(txtId.Text, gigDate.SelectedDate, txtVenue.Text, txtGenre.Text, Convert.ToDouble(txtCost.Text), Convert.ToInt32(txtCapacity.Text), chkHeadliner.Checked, txtMainAct.Text, chkEngineer.Checked);
}
addGig method:
public void addGig(GigOpportunity gigOpportunity)
{
//Make sure a gig with this id does not already exist
foreach (GigOpportunity g in gigList)
{
if (g.GigId == gigOpportunity.GigId)
{
throw new DuplicateIdException();
}
}
gigList.Add(gigOpportunity);
}
I understand now your problem. You musn't think like in windows form. You declared those method inside other form. When you call it by assigning a new Form object you will not get the value inside as they have been disposed after you change the page.
So in your case:
if (Application["getData"] != null)
{
Application["saveData"] = Application["getData"];
gigList.addGig((GigOpportunity)Application["getData"]);
UpdateListbox();
}
But I will suggest you to use Session object instead of Application object.
You can read more about it here
So you have to do like this:
if (Session["getData"] != null)
{
Session["saveData"] = Session["getData"];
gigList.addGig((GigOpportunity)Session["getData"]);
UpdateListbox();
}
You don't need to create the second form object AddGigForm and you must be sure to call your methodGetData in the form where is it declared to assign your Session.
I have a windows form application with a ComboBox on it and I have some strings in the box. I need to know how when I select one of the strings and press my create button, how can i make that name show up on another windows form application in the panel I created.
Here is the code for adding a customer
public partial class AddOrderForm : Form
{
private SalesForm parent;
public AddOrderForm(SalesForm s)
{
InitializeComponent();
parent = s;
Customer[] allCusts = parent.data.getAllCustomers();
for (int i = 0; i < allCusts.Length; i++)
{
Text = allCusts[i].getName();
newCustomerDropDown.Items.Add(Text);
newCustomerDropDown.Text = Text;
newCustomerDropDown.SelectedIndex = 0;
}
now when i click the create order button I want the information above to be labeled on my other windows form application.
private void newOrderButton_Click(object sender, EventArgs e)
{
//get the info from the text boxes
int Index = newCustomerDropDown.SelectedIndex;
Customer newCustomer = parent.data.getCustomerAtIndex(Index);
//make a new order that holds that info
Order brandSpankingNewOrder = new Order(newCustomer);
//add the order to the data manager
parent.data.addOrder(brandSpankingNewOrder);
//tell daddy to reload his orders
parent.loadOrders();
//close myself
this.Dispose();
}
The context is not very clear to me, but if I got it right, you open an instance of AddOrderForm from an instance of SalesForm, and when you click newOrderButton you want to update something on SalesForm with data from AddOrderForm.
If this is the case, there are many ways to obtain it, but maybe the one that requires the fewer changes to your code is this one (even if I don't like it too much).
Make the controls you need to modify in SalesForm public or at least internal (look at the Modifiers property in the Design section of the properties for the controls). This will allow you to write something like this (supposing customerTxt is a TextBox in SalesForm):
parent.customerTxt.Text = newCustomerDropDown.SelectedItem.Text;