Updating GUI components in class B from class A in c# - c#

EDIT: I see I'm getting a lot of downvotes on this post. I've tried to explain what I try to do, where my errors and in which direction want to go. I'm asking for insight in what I'm doing wrong. If you downvote; pleas tell me why, so I can improve the question. Thanks.
I'm creating an application where I have one main form, and several different User Controls which the user works on. This helps me splitting the code, managing the different parts of the program. And it would be easy to expand the application later on.
I'm trying to create a class where I manage the active controls I want to call one function in that class with as argument the form that should become active.
An image can illustrate how I try to setup this application. Note that the control manager class is not a seperate class in the code i show below, but a partial class of the mainform. Any tips on how to get it like in the image are very welcome :)
The class to manage all active forms looks like this: Please note that all user controls are just a user control with some buttons/textboxes etc on it. No code is added at all yet.
public partial class STP2Main
{
// I make each UserControl accessable for the whole class
SetupDeviceControl.SetupDevice SetupDev = new SetupDeviceControl.SetupDevice();
GenConfigFileControl.GenConfigFileControl GenConfFile = new GenConfigFileControl.GenConfigFileControl();
Monitoring.MonitoringControl Monitor = new Monitoring.MonitoringControl();
GenEncKeyControl.GenEncKeyControl GenEncKey = new GenEncKeyControl.GenEncKeyControl();
MenuControl.MenuControl MenuControl = new MenuControl.MenuControl();
public void SelectActiveWindow()
{
// Any active control should be hidden thats what this function does:
HideCurrentActiveControl();
// Check whether the window is already created
if (!WindowExists())
{ // if not created; create the windows:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl: // control 1:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated = true;
SetupDev.Parent = this;
SetupDev.Location = new Point(3, 30);
SetupDev.Show();
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl: //control 2:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
STP_Design.ProgramParameters.C.MonitoringControlIsCreated = true;
Monitor.Parent = this;
Monitor.Location = new Point(3, 125);
Monitor.Show();
Monitor.BringToFront();
break;
case STP_Data.Data.MenuControl: // control 3
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
STP_Design.ProgramParameters.C.MenuControlIsCreated = true;
MenuControl.Location = new Point(3, 30);
MenuControl.Parent = this;
MenuControl.Show();
MenuControl.BringToFront();
break;
}
}
else
{ // window is already created so needs to be called to front again:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
Monitor.Visible = true;
Monitor.BringToFront();
break;
case STP_Data.Data.AdvancedMenu:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.AdvancedMenu;
tabControl1.Visible = true;
tabControl1.BringToFront();
break;
case STP_Data.Data.MenuControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
MenuControl.Visible = true;
MenuControl.BringToFront();
break;
}
}
btnMenu.BringToFront();
}
// some functions which are called above are not shown; not relevant for this question
}
What I experience is the following: I get no errors at all. But the controls simply not change at all. If I call a window, it is created only once, because I did make it as partial class of my Mainform. (I've tried a complete seperate class, which did result in errors with threading, As I am not an experienced c# programmer, I tried to avoid that using a partial class.)
I'll add another function; which does not do anything at all:
private void HideCurrentActiveControl()
{
switch (STP_Design.ProgramParameters.C.CurrentActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
SetupDev.Visible = false;
break;
case STP_Data.Data.MonitoringControl:
tabControl1.Visible = false;
Monitor.Visible = false;
break;
case STP_Data.Data.GenConfFileControl:
GenConfFile.Visible = false;
break;
case STP_Data.Data.GenEncKeyControl:
GenEncKey.Visible = false;
break;
case STP_Data.Data.MenuControl:
MenuControl.Visible = false;
break;
case STP_Data.Data.AdvancedMenu:
tabControl1.Visible = false;
break;
default:
tabControl1.Visible = false;
break;
}
}
I've tried debugging this part of code and it executes the statements, but I see no changes at all.
I think I've shown what I am trying to do; and how I try to do that. My question is: How do I acces those forms so I can manage them from a seperate class (or in this case partial class of the main form).
Then I have this last function, which does some wierd things. Before I call the SelectActiveWindow() function I update the variable STP_Design.ProgramParameters.C.NextActiveControl to for example: ...AdvancedMenu. (this was before that ...MenuControl) But it does always show that it is still MenuControl. Nowhere in my code is something where I change that value besides right before I start the function. (I've also tried to make the nextcontrol as an argument of the function SelectActiveWindow() but this did the same)
private bool WindowExists()
{
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
if (STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated)
return true;
else
return false;
case STP_Data.Data.MonitoringControl:
if (STP_Design.ProgramParameters.C.MonitoringControlIsCreated)
return true;
else
return false;
case STP_Data.Data.GenConfFileControl:
if (STP_Design.ProgramParameters.C.GenConfFileIsCreated)
return true;
else
return false;
case STP_Data.Data.GenEncKeyControl:
if (STP_Design.ProgramParameters.C.GenEncKeyControlIsCreated)
return true;
else
return false;
case STP_Data.Data.AdvancedMenu:
return true;
case STP_Data.Data.MenuControl:
if (STP_Design.ProgramParameters.C.MenuControlIsCreated)
return true;
else
return false;
default:
return false;
}
}
Summery of what I am looking for:
I am having a main form where display different user controlls in. I am trying to create a seperate class which is accessable from each control/form in my project. This class should manage the controls which are shown. In the code above I illustrated how I tried to do this, but this does not result in the expected result.

Ok, Now I understand the context needed. We actually do something very similar in my program. Here is a basic outline of how we do it...
Layout
On the main form we have a Panel container that we call pnlMain. It is this control that we add and remove active user controls from. We also have a UserControl object at a global level on the form representing curActiveControl.
Code
When the user selects a window via one of the menu's, we run a function that looks like this
switch (UserSelection)
{
case "Page 1":
if(curActiveControl.GetType() != typeOf(Page1Control))
{
pnlMain.Controls.Remove(curActiveControl);
curActiveControl = new Page1Control();
//do setup and configuration things
pnlMain.Controls.Add(curActiveControl);
}
//do some post processing things
break;
//other pages/specific page controls
}
Refresh();
The downside to this specific method is that the pages themselves are not persistent, so if there are entries or variables you want to have active across a session rather than only while on a page, you have to store them in some other global object and reload them from the user control's Load or Constructor methods.
You could do this same thing but instead of creating a new control instance each time for curActiveControl you could simply replace it with the standby instance of the new control. Be careful with referencing and overwriting though, its not something I personally have tried before.
The key in the method we use is the Panel that holds the user controls. Rather than adjusting the visibility and Z-Order of a large number of user controls, we simply change the displayed control in the main panel and the other control don't even exist at any given point in time.
The other wrinkle is that this functionality is directly on our Main Form. I Don't know how well this will work as another partial class. Its definitely worth a try though.

Related

Accessing class from form and vice-versa

After hunting the internet for two days and not finding a solution that I can understand properly I have to ask on here for an answer.
I have a windows forms application that was written in vb.net and works fine. I have decided to rewrite this in c# which I thought wouldn't be too much of a problem but ...
I have two classes in the project :
FormJobs & AppJobs
FormJobs contains methods and functions that modify the forms in some way.
AppJobs contains methods and functions for everything else (Checks,Scanning and so forth).
On my main form (FrmStart) the On_load event uses a function from AppJobs to check that the network is up (public bool CheckNetConnection) and then Checks to make sure that the root save folder exists (public void CheckRoot).
If CheckNetConnection is false or CheckRoot does not exist then a method in the FormJobs class sets some buttons to disabled, some labels to display information as to what has gone wrong and also sets the height of the form.
The above works in VB.net but I keep getting a StackOverflowException or NullReferenceException with the C# code.
I know the reason for the Exceptions is because the two classes and the form all keep calling each other so I know that I need to remove this code but I am not sure how to let each class and the form access each other. It is obviously bad design as I`m just starting to learn C# so any help on this would be much appreciated.
But my main questions are:-How do I get a form to access multiple classes?
Allow the classes to access each other?
Let the classes make changes to a form?
FrmStart Code
AppJobs Appjobs = new AppJobs();
private void FrmStart_Load(object sender, EventArgs e)
{
KeyPreview = true;
if (Appjobs.CheckNetConnection(this) == true)
{
Appjobs.CheckRoot(this);
}
AppJobs Code
public class AppJobs
{
FormJobs Formjobs = new FormJobs();
public string AppRoot = Properties.Settings.Default.DefaultFolder;
public string DefaultDevice = Properties.Settings.Default.DefaultScanner;
public bool NoDirectory = false;
DialogResult MsgBoxQuestion;
public bool CheckNetConnection(Form StartForm)
{
IPHostEntry ServerIP = new IPHostEntry();
bool ConnectedToServer = false;
string CurrentRoot = "MyServer";
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
try
{
IPHostEntry DNSTest = Dns.GetHostEntry(CurrentRoot);
if (DNSTest.AddressList.Length > 0)
{
ConnectedToServer = true;
}
else
{
ConnectedToServer = false;
}
}
catch (System.Net.Sockets.SocketException ex)
{
ConnectedToServer = false;
}
}
return ConnectedToServer;
}
public void CheckRoot(Form StartForm)
{
if (string.IsNullOrEmpty(AppRoot))
{
Formjobs.SetHeight(StartForm);
return;
}else if(AppRoot == "0")
{
Formjobs.SetHeight(StartForm);
return;
}
else
{
if ((!Directory.Exists(AppRoot)))
{
NoDirectory = true;
MsgBoxQuestion = MessageBox.Show(AppRoot + " is set, but the directory does not exist." + Environment.NewLine
+ Environment.NewLine + "Would you like to create the folder now?", "Root folder missing", MessageBoxButtons.YesNo);
if (MsgBoxQuestion == DialogResult.Yes)
{
Directory.CreateDirectory(AppRoot);
NoDirectory = false;
}
else
{
MessageBox.Show("You will not be able to use this program until you create a root folder.", "No root folder selected",MessageBoxButtons.OK);
}
}
}
}
}
FormJobs Code
public class FormJobs
{
AppJobs Appjobs = new AppJobs();
public void SetHeight(Form StartForm)
{
if (Appjobs.AppRoot == null | Appjobs.AppRoot == "0") {
if (Appjobs.DefaultDevice == null | Appjobs.DefaultDevice == "0") {
if (StartForm.Controls["MenuStrip1"].Visible == true) {
StartForm.Height = 167;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 24);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 48);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}else
{
StartForm.Height = 147;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 9);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 33);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}
}
One of the causes of your problems is that everyone is changing your StartForm. Apart from that this spaghetti makes it difficult to understand, it certainly doesn't help to make your classes reusable and maintainable if your Startform changes.
It seems to me, that AppJobs is meant to decide what the form should look like (for instance it decides that the StartForm should change height), while FormJobs performs the calculations needed to change this height. StartForm apparently is just allowing to let everyone make changes to him.
A better design would be that StartForm would not ask AppJobs to change its size, and to ask the operator whether a folder should be generated. Instead if ought to ask appJobs for advise: "Which height do you think I should have". after that it could ask FormJobs: "Please adjust my height according to this specification"
FormJobs should trust StartForm that it has gathered the correct information about how a StartForm ought to look like. FormJobs should not ask AppJobs for any information: "Hey AppJobs, StartForm asked me to change its appearance to certain specifications, but I'm not certain whether StartForm has done its job correctly. Please tell me if these specifications are correct, and give me some missing information")
The correct division into tasks would be:
AppJobs specifies the format of any StartForm according to its internal state (a.o. AppRoot, and existence of certain folders)
StartForm is the one who displays all items. He decides who to ask for specifications, and what to do with the returned specifications. He is also the only one who communicates with operators
FormJobs is a class that apparently knows all elements from a StartForm. If you will only have one type of StartForm, then Appjobs should be part of the Startform class. If you think there might be several different Startform classes, all with the same elements that ought to be manipulated similarly, shouldn't all these StartForm classes be derived from a FormJobs class?
Anyway, redesign without everyone causing to manipulate StartForm
Apparently there are a limited number of StartForm layouts depending on AppRoot, defaultDevice etc. You seem to be missing some "else" after your if, so this list might not be accurate. Still you will get the idea:
enum StartFormLayouts
{
DefaultDevice0,
AppRoot0,
Other,
}
// class that specifies the layout of any startform
class AppJobs
{
private bool IsAppRoot0
{
get{return Appjobs.AppRoot == null || Appjobs.AppRoot == "0";}
}
private bool IsDefaultDevice0
{
get{return Appjobs.DefaultDevice == null || Appjobs.DefaultDevice == "0";}
}
public StartFormLayoug GetPreferredLayout()
{
if (this.IsAppRoot0)
{
if (this.IsDefaultDevice)
{
return StartFormLayout.DefaultDevice0;
}
else
return StartFormLayout.AppRoot0;
}
else
{
return StartFormLayout.Other;
}
}
public bool ShouldAskDirectoryCreation()
{
return (!this.IsAppRoot0 && !Directory.Exists(AppRoot));
}
}
Note that this class doesn't need StartForm, nor AppJobs. It could work with any class that wants to know if it should ask for DirectoryCreation. Since it also does not speak any language, even a Chinese StartForm could use it. After all, the StartForm is the only one who knows what language it speaks and what to do if a certain layout is requested.
Furthermore, did you notice that I used a double || to use a Boolean OR instead of a bitwise or?
And I use statements like if (a) instead of if(a=true) a C# Boolean is a real Boolean, in contradiction to Booleans in C and C++.
The class of all kinds of forms that should be able to be layout according to the requested layout contains the functions similar to your
It depends a bit of whether you decide to let it be a base class of StartForm or StartForm itself. If you want it to handle every form class that has the required controls, consider of using an interface:
public Interface IStartForm
{
public int Height {get; set;}
public Label LabelNoRoot {get;}
public Label LabelNoDevice {get; }
public Button BtnTickets {get;}
...
This way you can set the size of any form that has these labels and buttons, even if they have different names than those strings you use.
But again: if you ever only want to size StartForm, then this should be a function in StartForm.
public SetHeight(StartFormLayout layout, IStartForm startForm)
{
switch (layout)
{
case StartFormLayout.DefaultDevice0:
if (startForm.MenuStrip.Visible)
{
startForm.Height = ...;
startForm.LabelNoRoot.Location = ...
// etc
}
else
{
...
Noticed that because of this separation of concerns the AppJobs and FormJobs don't have to know each other. AppJobs and FormJobs also don't really have to know what 'StartForm` is, only that it has the labels and buttons etc that it needs to change.
class StartForm : Form, IStartForm
{
public Label LabelNoRoot {get{return this.label1; } }
...
private void FrmStart_Load(object sender, EventArgs e)
{
AppJobs layoutdesigner = new AppJobs(...);
StartFormLayout layoutdesigner = layouter.GetPreferredLayout();
FormJobs layouter = new FormJobjs();
layouter.SetHeight(this)
}
Noticed that my form didn't have a label named "LabelNoRoot", but a Label1 that should function as a LabelNoRoot. Also: because I used types instead of string, You can be certain that I can't handle a label as if it was a button. I can't by accident try to press the label. Something that could easily been done when you were using strings to identify the items you want to layout.
Extending the comments: you just remove the new part in your FormJobs and AppJobs classes.
leaving the code in i.e. in the FormJobs class like : AppJobs appObj;
Then in your main form create at some point a FormJobs obj and an AppJobs obj and set its property.
I.e. in main Form:
AppJobs appObj = new AppJobs();
FormJobs formObj = new FormJobs();
formObj.appObj = appObj;
Tho I must say i dont like that approach you are taking with this...
You should think of another way or at least refactor your code that FormJobs does not need AppJobs methods and vice versa in a way that all calls to FormJobs and AppJobs come from your main form.

Effective way to set the Controls enable/disable/hidden on UI

I am working on UI where i have some controls like textbox, button, radiobutton and more.
On some specific business workflows i have to play with my controls and set their state as enable/disable or set visibility of them.
When i do this my whole UI code behind (xaml.cs) scattered with controls enabling and disabling.
i want to write a single method which is completely responsible for handling the state of my UI controls.
Currently what i have done is - making a single function which take the operation as parameter and then based on operation i am playing with my controls.
For example:
private const string ADD_OPERATION = "Add";
private const string MODIFY_OPERATION = "Modify";
private const string DELETE_OPERATION = "Delete";
-------------------------------------------------------
/// <summary>
/// Method for disabling controls present on current screen
/// based on various operations like add, delete, edit identity
/// </summary>
private void EnableOrDisableIdentityControl(string operation)
{
switch (operation)
{
case ADD_OPERATION:
this.EditIdentificationGroupBox.IsEnabled = true;
this.AddUpdateIdentificationButton.IsEnabled = true;
this.RelatedEntitiesGridFooter.IsAddButtonEnabled = false;
this.RelatedEntitiesGridFooter.IsEditButtonEnabled = false;
this.RelatedEntitiesGridFooter.IsDeleteButtonEnabled = false;
this.IdentificationDataGrid.IsEnabled = false;
break;
case MODIFY_OPERATION:
this.EditIdentificationGroupBox.IsEnabled = true;
// Disable identity grid
this.IdentificationDataGrid.IsEnabled = false;
this.RelatedEntitiesGridFooter.IsAddButtonEnabled = false;
this.RelatedEntitiesGridFooter.IsEditButtonEnabled = false;
this.RelatedEntitiesGridFooter.IsDeleteButtonEnabled = false;
this.EditIdentificationGroupBox.Focus();
break;
case DELETE_OPERATION:
this.EditIdentificationGroupBox.IsEnabled = false;
break;
default:
this.EditIdentificationGroupBox.IsEnabled = false;
if (this.IdentificationDataGrid.Items.Count == 0)
{
this.RelatedEntitiesGridFooter.IsAddButtonEnabled = true;
this.RelatedEntitiesGridFooter.IsEditButtonEnabled = false;
this.RelatedEntitiesGridFooter.IsDeleteButtonEnabled = false;
}
else
{
this.RelatedEntitiesGridFooter.IsAddButtonEnabled = true;
this.RelatedEntitiesGridFooter.IsEditButtonEnabled = true;
this.RelatedEntitiesGridFooter.IsDeleteButtonEnabled = true;
}
break;
}
}
I want to know is there is any better approach for effectively handling controls state in code behind?
I am not sure using winform way of code-behind handling is right way to go. WPF was specifically designed to get rid of tight coupling of view with code-behind. I would suggest to use MVVM pattern (Model-View-ViewModel) intended for WPF which would solve all these issues you mentioned.

Managing EventHandlers within a large Form

I'm developing a WinForm application and I've done a pretty bad job thus far of managing the size and contents. I was hoping someone could give me an example of how to break out some of the logic that I have within the main form cs file.
Here is an example of an EventHandler function that I have within my MainWindow.cs:
private void GroupBoxRequestTypeCheckedChanged(object pSender, EventArgs pEventArgs)
{
RadioButton vRadioButton = pSender as RadioButton;
if (vRadioButton != null)
{
this.fSelectedButton = vRadioButton.Checked ? vRadioButton : null;
if (vRadioButton.Equals(this.RadioButton_Copy) || vRadioButton.Equals(this.RadioButton_Delete) || vRadioButton.Equals(this.RadioButton_Download)
|| vRadioButton.Equals(this.RadioButton_Move) || vRadioButton.Equals(this.RadioButton_Upload))
{
this.GroupBox_Files.Enabled = true;
this.GroupBox_Variables.Enabled = false;
}
else
{
this.GroupBox_Files.Enabled = false;
this.GroupBox_Variables.Enabled = true;
}
if (this.fSelectedButton != null)
{
if (this.fSelectedButton.Equals(this.RadioButton_Delete))
{
this.TextBox_DestinationFile.Enabled = false;
this.Button_DestinationBrowse.Enabled = false;
}
else
{
this.TextBox_DestinationFile.Enabled = true;
this.Button_DestinationBrowse.Enabled = true;
}
}
}
}
So this is simply one of many EventHandler's that I have within a Form. I created a MainForm which has a Tabbed Pane and has a collection of Tabs which have buttons, textboxes, checkboxes etc in each tab. All of the events that I handle go into the MainForm.cs file and now I've got close to 1,000 lines in this one file.
Can someone give me a simple example (or a article/document) detailing good structure? Can I define my EventHandler functions in a separate class (if so, how would this work...) Do I create some sort of static Helper class where I simply pass the instance of the objects i need to manipulate? I.E.
private void GroupBoxRequestTypeCheckedChange(object pSender, EventArgs pEventArgs)
{
HelperClass.HandleGroupBoxRequestTypeCheckedChanged(pSender, pEventArgs, this);
}
Where 'this' is the Form itself which has all the references to the objects I need to manipulate?
It's probably worth noting that I've learned a good bit about the Cross-Thread calls and I've started making Extension methods for many instances that I need which are simplistic.
Another question - I notice that the Visual Designer automatically makes all Components created with it private by default, is it in general a bad idea to make these internal and use the form object to reference these components as needed from outside the class? If it is not a good idea, what is better?
First I would suggest to separate independent user-interface parts into UserControls or Components. Then - if needed - wire them using Events (eg. your own specialized events and properties.
For example you can place your main content (the TabControl / Container) in a UserControl and place that user control in the main form. All tab-/page-switching logic/UI etc. then belongs to that user control. In that UserControl you can define for example your own Event that gets fired when the user switches a tab. The main form then can register to this event - just like it can for other Winforms-control-events - and do its stuff (eg. change the window title to represent the currently active tab).
Then next you can move the content of each tab to its own user-control and use these user-controls within your new tabs-usercontrol. Move the logic down to the UserControl which is responsible for the given task.
A form/controls hierarchy from some typical application could look like this:
MainForm (Form)
MainTabContainerControl (UserControl)
Page1Control (UserControl)
Page2Control (UserControl)
MyImprovedDbRowGridControl (UserControl or Component)
Page3Control (UserControl)
SidebarControl (UserControl)
SearchControl (UserControl)
MyImprovedDbRowGridControl (UserControl or Component)
QuickHelpControl (UserControl)
Next thing is so keep all the UI-eventhandlers as small as possible and doing only UI stuff. Move other logic like business- or dataaccess-logic to other classes outside of the user-interface.
If you have combinations of the controls that are needed more then once in the application: move them to a re-usable UserControl. (eg. breadcrum).
Regarding your sample code you can make it more compact and therefore maintainable by simplyfing its logic:
if (this.fSelectedButton.Equals(this.RadioButton_Delete))
{
this.TextBox_DestinationFile.Enabled = false;
this.Button_DestinationBrowse.Enabled = false;
}
else
{
this.TextBox_DestinationFile.Enabled = true;
this.Button_DestinationBrowse.Enabled = true;
}
...could be:
var delete = fSelectedButton == RadioButton_Delete;
this.TextBox_DestinationFile.Enabled = !delete;
this.Button_DestinationBrowse.Enabled = !delete;
Update:
When it comes to refactoring and code-cleanup a very usefull tool is Resharper (R#). I can highly recommend it.
Hope this gives you some ideas where to start.

How to correctly solve this situation regarding DataContext, IDisposable and Controls.Clear()

I'm using Entity Framework 4 as my ORM on a Windows Forms application.
I have a series of UserControls that function as if they were forms or areas inside my MainForm.cs. The reason I did this was to easily interchange what to display in the 'content' block of the form.
So when I click on the buttons (on the left), I .Clear() whatever controls is currently in the 'content' block and add the select form.
Here's the relevant code:
private void navigationBar_Click(object sender, EventArgs e)
{
//panelHolder is a regular Winforms Panel control.
panelHolder.Controls.Clear();
switch (sender.ToString())
{
case "alumnos":
var studentForm = new Students.StudentListerForm();
panelHolder.Controls.Add(studentForm);
break;
case "personal":
var personalForm = new Personal.PersonalListerForm();
panelHolder.Controls.Add(personalForm);
break;
case "atendencia":
var atendenciaForm = new Attendance.StudentAttendanceForm();
atendenciaForm.ShowDialog();
break;
case "cursos":
var gradeForm = new Grades.GradeListerForm();
panelHolder.Controls.Add(gradeForm);
break;
case "centralizador":
MessageBox.Show("est");
break;
case "libretas":
Scores.StudentScores scores = new Scores.StudentScores();
panelHolder.Controls.Add(scores);
break;
}
}
Now, each UserControl manages it's own creation and usage of the data context. Inside of each of these controls I have code for example:
using (GradeRepository repo = new GradeRepository())
{
cmbGrade.DataSource = repo.FindAllGrades();
}
And here's the code for GradeRepository:
public class GradeRepository : IDisposable
{
ColegioDBV2Entities db = new ColegioDBV2Entities();
public IQueryable<Grade> FindAllGrades()
{
return db.Grades;
}
public void Add(Grade grade)
{
db.AddToGrades(grade);
}
public void SaveChanges()
{
db.SaveChanges();
}
public void Dispose()
{
db.Dispose();
}
}
This ensure I use the context, get data, close it and dispose of it.
My problem lies when I click on one of the buttons I told you about up top, the panelHolder.Controls.Clear(); line fires ObjectDisposedException.
I've temporarily solved this by removing the using statements in the relevant areas, so it now looks like:
GradeRepository repo = new GradeRepository();
cmbGrade.DataSource = repo.FindAllGrades();
Can anybody suggest a correct way to tackle this problem? Will the .Clear() method successfully dispose of any objects, so using a using statement is not needed?
Thank you for your time.
You are likely returning an IQueryable<T> which supports deferred execution. This means, you return the IQueryable<T> but then dispose the attached DataContext. When the IQuerable<T> is executed (sometime later), it tries to access the DataContext which has now been disposed. You could probably do this:
cmbGrade.DataSource = repo.FindAllGrades().ToList();
Make the DataContext as a property on the scope of the form and let it destroy when the form is destroyed.

Threading with Windows Forms

I've written a Windows Forms application in C#. When I run a separate thread containing a method that toggles the invisibility of a panel on my form, it works the first time but not the second. Why and how can I fix it?
Thanks, solved My Problem by follow Code :
Panel tmp = null;
switch (d.Person)
{
case 1: tmp = backPic1;
break;
case 2: tmp = backPic2;
break;
case 3: tmp = backPic3;
break;
}
if (InvokeRequired)
{
tmp.Invoke(new MethodInvoker(delegate() { tmp.Visible = true; }));
}
else
{
tmp.Visible = true;
}
My guess be he UI code invoking from a background thread is. ;)
Your question is a bit vague, but it sounds like you want to control the UI from a different thread, in which case you will need to synchronise the request. It's difficult to tell you how to do that without knowing what programming language you are using.

Categories

Resources