designing a good way enable/disable controls [modified]
-
hi, I've finished all the base code to my App. Tested it and everything, now I need to make a UI. Its not going to be overly complex but it could get complex later on, so I want to design it well. I want a proper way to enable/disable UI but later being able to change maybe the real control, so far i've come up with.
interface IMainForm//implement this in the main form.
{
IUIController GetUIController(string name);
}
interface IUIController
{
bool Enabled
{ get;set;}
}The default implementation would be:
class DefUIController : IUIController
{
DefUIController(Control cntrl);
{
}
//encapsulate Controls.Enabled
}And then in the main form I could search for the control and create a new UIController and return it, like this:
IUIController GetUIController(string name)
{
foreach(Control crt in this.Controls)
{
if(crt.Name== name)
{
return DefUIController(crt);
}
return null;
}
}I would need to change the state of a control from a sub UserControl which has a reference via a property to IMainForm. Like, if the selected Customer in the CustomerGridView UserControl doesn't have a bill yet, _within_ the usercontrol i could do this:
IUIController ui = _mainform.GetUIController("mnuPrintBill");//Menu
ui.Enabled = false;Is this design good enough or is there a method out there, I don't need something complex like CAB or something, its not such a big app. Thanks so much. Gideon
modified on Thursday, November 13, 2008 12:07 AM
-
hi, I've finished all the base code to my App. Tested it and everything, now I need to make a UI. Its not going to be overly complex but it could get complex later on, so I want to design it well. I want a proper way to enable/disable UI but later being able to change maybe the real control, so far i've come up with.
interface IMainForm//implement this in the main form.
{
IUIController GetUIController(string name);
}
interface IUIController
{
bool Enabled
{ get;set;}
}The default implementation would be:
class DefUIController : IUIController
{
DefUIController(Control cntrl);
{
}
//encapsulate Controls.Enabled
}And then in the main form I could search for the control and create a new UIController and return it, like this:
IUIController GetUIController(string name)
{
foreach(Control crt in this.Controls)
{
if(crt.Name== name)
{
return DefUIController(crt);
}
return null;
}
}I would need to change the state of a control from a sub UserControl which has a reference via a property to IMainForm. Like, if the selected Customer in the CustomerGridView UserControl doesn't have a bill yet, _within_ the usercontrol i could do this:
IUIController ui = _mainform.GetUIController("mnuPrintBill");//Menu
ui.Enabled = false;Is this design good enough or is there a method out there, I don't need something complex like CAB or something, its not such a big app. Thanks so much. Gideon
modified on Thursday, November 13, 2008 12:07 AM
Hello, I am not sure if it is a good suggestion or not as I have done it myself but you can use Command pattern for your application. You can use databinding to bind several ui controls to one ICommand object and then changing enabled/visible property of the ICommand will automatically enable/disable, hide/show by the magic of databinding :)
Giorgi Dalakishvili #region signature My Articles Asynchronous Registry Notification Using Strongly-typed WMI Classes in .NET [^] My blog #endregion
-
Hello, I am not sure if it is a good suggestion or not as I have done it myself but you can use Command pattern for your application. You can use databinding to bind several ui controls to one ICommand object and then changing enabled/visible property of the ICommand will automatically enable/disable, hide/show by the magic of databinding :)
Giorgi Dalakishvili #region signature My Articles Asynchronous Registry Notification Using Strongly-typed WMI Classes in .NET [^] My blog #endregion
hi, Thanks you guys, but un fortunately UI needs to be disabled based on more complicated situations. Like User permissions, and things like say if its a customer's last day of stay, stuff like that. I will have a customer grid, so if a certain customer is on his last day, in the user control I would do this:
//on selected reservation changed. if(selectedReservation.EndDate == DateTime.Today) { //must enable the CheckOut Reservation menu item. } else { //must disable the CheckOut Reservation menu item. }
I can't put all possibilities into an Enum, and I think databinding would be a little convoluted since some situations are more complex. Is my design stupid? that I'm looping through the controls? Thanks so much. -
hi, Thanks you guys, but un fortunately UI needs to be disabled based on more complicated situations. Like User permissions, and things like say if its a customer's last day of stay, stuff like that. I will have a customer grid, so if a certain customer is on his last day, in the user control I would do this:
//on selected reservation changed. if(selectedReservation.EndDate == DateTime.Today) { //must enable the CheckOut Reservation menu item. } else { //must disable the CheckOut Reservation menu item. }
I can't put all possibilities into an Enum, and I think databinding would be a little convoluted since some situations are more complex. Is my design stupid? that I'm looping through the controls? Thanks so much.giddy_guitarist wrote:
Is my design stupid? that I'm looping through the controls?
I don't think there is much else to do really. It just ties your code really tight to your business rules in the UI. You may want to take a hybrid look and do both. Look at what can be done via a form based state machine then augment that with some business rule specific stuff.
-
hi, Thanks you guys, but un fortunately UI needs to be disabled based on more complicated situations. Like User permissions, and things like say if its a customer's last day of stay, stuff like that. I will have a customer grid, so if a certain customer is on his last day, in the user control I would do this:
//on selected reservation changed. if(selectedReservation.EndDate == DateTime.Today) { //must enable the CheckOut Reservation menu item. } else { //must disable the CheckOut Reservation menu item. }
I can't put all possibilities into an Enum, and I think databinding would be a little convoluted since some situations are more complex. Is my design stupid? that I'm looping through the controls? Thanks so much.Hi As Giorgi mentioned, the command pattern allows you the control of enabling/disabling. You will find an example for WPF here WPF Command-Pattern Applied[^] Here you will find an example for WinForms[^]. Regards, Jani
-
hi, I've finished all the base code to my App. Tested it and everything, now I need to make a UI. Its not going to be overly complex but it could get complex later on, so I want to design it well. I want a proper way to enable/disable UI but later being able to change maybe the real control, so far i've come up with.
interface IMainForm//implement this in the main form.
{
IUIController GetUIController(string name);
}
interface IUIController
{
bool Enabled
{ get;set;}
}The default implementation would be:
class DefUIController : IUIController
{
DefUIController(Control cntrl);
{
}
//encapsulate Controls.Enabled
}And then in the main form I could search for the control and create a new UIController and return it, like this:
IUIController GetUIController(string name)
{
foreach(Control crt in this.Controls)
{
if(crt.Name== name)
{
return DefUIController(crt);
}
return null;
}
}I would need to change the state of a control from a sub UserControl which has a reference via a property to IMainForm. Like, if the selected Customer in the CustomerGridView UserControl doesn't have a bill yet, _within_ the usercontrol i could do this:
IUIController ui = _mainform.GetUIController("mnuPrintBill");//Menu
ui.Enabled = false;Is this design good enough or is there a method out there, I don't need something complex like CAB or something, its not such a big app. Thanks so much. Gideon
modified on Thursday, November 13, 2008 12:07 AM
I think using the MVC pattern is a good solution. I use it all the time. With events the whole process becomes easy. Create an event in your business object called Validated or something, have the User Interface subscribe to this event. Within the handler put the logic for enabling/disabling control. Find out ALL the condition which will enable and disable your control and use boolean logic like below: nameOfButton.Enabled = customer.IsActive && customer.IsValid && someotherCondition || someotherCondition && (someotherCondition || !somotherCondition) I like this solution because all the rules for the ability of my control are in one spot and the button will only be enabled if all conditions are satisfied. One thing you want to stay away from is code such as nameOfButton.Enabled = true. Reason being is that somewhere another programmer, or yourself will have another similar call that disables the button. The latest call will actually decide the ability of the button. In situations like this you end up with a lot of if statements and things become very ugly soon.
-
I think using the MVC pattern is a good solution. I use it all the time. With events the whole process becomes easy. Create an event in your business object called Validated or something, have the User Interface subscribe to this event. Within the handler put the logic for enabling/disabling control. Find out ALL the condition which will enable and disable your control and use boolean logic like below: nameOfButton.Enabled = customer.IsActive && customer.IsValid && someotherCondition || someotherCondition && (someotherCondition || !somotherCondition) I like this solution because all the rules for the ability of my control are in one spot and the button will only be enabled if all conditions are satisfied. One thing you want to stay away from is code such as nameOfButton.Enabled = true. Reason being is that somewhere another programmer, or yourself will have another similar call that disables the button. The latest call will actually decide the ability of the button. In situations like this you end up with a lot of if statements and things become very ugly soon.
Interesting, I've been quiet for sometime because I was doing a little more thinking, I decided to use the MVP pattern for each UserControl(View) that I make, however what I was talking about was Enabling/Disabling a control in the MainForm from a UserControl, I would end up having a reference to the MainForm from the UserControl then, which glues the UserControl to the MainForm! MainForm --------------------- CustomerView(UserControl): A customer is selected, something needs to be disabled in the MainForm. BillView(UserControl) --------------------- But now, It seems I will only have a MenuBar and a ToolBar on the MainForm, there will also be a TabControl and inside these TabControls will reside different views. So I just have to bother about diabling/enabling menus and toolstripitems. Now, I thought of encapsulating the Toolbar and MenuBar and have themselves decide what needs to be enabled and disabled instead. Like class HmsMenuBar : MenuStrip { //during the OnDropDownOpening.. i can check if items should be enabled/disabled.?? } Same thing for the ToolBar, does this sound ok? Thanks so much Gideon
-
Interesting, I've been quiet for sometime because I was doing a little more thinking, I decided to use the MVP pattern for each UserControl(View) that I make, however what I was talking about was Enabling/Disabling a control in the MainForm from a UserControl, I would end up having a reference to the MainForm from the UserControl then, which glues the UserControl to the MainForm! MainForm --------------------- CustomerView(UserControl): A customer is selected, something needs to be disabled in the MainForm. BillView(UserControl) --------------------- But now, It seems I will only have a MenuBar and a ToolBar on the MainForm, there will also be a TabControl and inside these TabControls will reside different views. So I just have to bother about diabling/enabling menus and toolstripitems. Now, I thought of encapsulating the Toolbar and MenuBar and have themselves decide what needs to be enabled and disabled instead. Like class HmsMenuBar : MenuStrip { //during the OnDropDownOpening.. i can check if items should be enabled/disabled.?? } Same thing for the ToolBar, does this sound ok? Thanks so much Gideon
UI controls, whether the main form or the User Control is just a mechanism to allow a user to interact with the underlying. What I do not understand is why you want the user control to enable/disable main forms controls: They must know about each others controls and adds to coupling which is not ideal. If you want a menu item to enable/disable based on customer's last day or whatever, then have both the main form and the user control subscribe to the customer. UserControl will do what it is supposed to do and main form will do what it is supposed to do. Now these UI elements only know about the "thing", in this case the Customer, they are displaying but not about each other. It will be like this: Customer is loaded and obviously properties will change, then the UI Control will subscribe to an event from customer--you have to create the events based on your requirements. In this handler, the control will ask the customer for whatever it is interested in, for example, IsLastDayOfStay, if true will enable itself and false otherwise. The main form will also subscribe, and ask for something else and mold itself accordingly. You can also design it so the form does not need to ask the Customer, but the event arguments can have the information in it. For this, you would need to create a simple class to encapsulate even arguments. The only problem is the controls are tied to your object. If I am not understanding what you want to do, then just write in plain English with no code what it is you want to achieve and hopefully I or someone else can give you a suggestion.
-
UI controls, whether the main form or the User Control is just a mechanism to allow a user to interact with the underlying. What I do not understand is why you want the user control to enable/disable main forms controls: They must know about each others controls and adds to coupling which is not ideal. If you want a menu item to enable/disable based on customer's last day or whatever, then have both the main form and the user control subscribe to the customer. UserControl will do what it is supposed to do and main form will do what it is supposed to do. Now these UI elements only know about the "thing", in this case the Customer, they are displaying but not about each other. It will be like this: Customer is loaded and obviously properties will change, then the UI Control will subscribe to an event from customer--you have to create the events based on your requirements. In this handler, the control will ask the customer for whatever it is interested in, for example, IsLastDayOfStay, if true will enable itself and false otherwise. The main form will also subscribe, and ask for something else and mold itself accordingly. You can also design it so the form does not need to ask the Customer, but the event arguments can have the information in it. For this, you would need to create a simple class to encapsulate even arguments. The only problem is the controls are tied to your object. If I am not understanding what you want to do, then just write in plain English with no code what it is you want to achieve and hopefully I or someone else can give you a suggestion.
I kinda understood what your saying better after looking at paint.net source code lol! I've been looking at a lot of programs like that for inspiration. So the Main form code itself should decide what menus and toolbars need to be enabled/disabled by querying/using business objects itself? That would be a correct design? (Atleast thats how it is in Paint.NET) (I'm sorry if i sound daft from time to time, I'm young and not formally computer educated!)
-
hi, Thanks you guys, but un fortunately UI needs to be disabled based on more complicated situations. Like User permissions, and things like say if its a customer's last day of stay, stuff like that. I will have a customer grid, so if a certain customer is on his last day, in the user control I would do this:
//on selected reservation changed. if(selectedReservation.EndDate == DateTime.Today) { //must enable the CheckOut Reservation menu item. } else { //must disable the CheckOut Reservation menu item. }
I can't put all possibilities into an Enum, and I think databinding would be a little convoluted since some situations are more complex. Is my design stupid? that I'm looping through the controls? Thanks so much.I would split the UI management into 2 distinct types, 1 based on permissions and user group membership and 2 state of the data. Either way it is custom coding for each form. I like the idea of binding the enabled/visible attribute. I use a permissions table that is returned from the login with all the permissions for the logged in user. Then each form checks this table for defined controls. While I implement this in all apps it is rarely used(corporate).
Never underestimate the power of human stupidity RAH