I'm making a game, and it may have modal UI windows, like popover windows.
I encapsulated all the fiddling into my class and I just call one method to show such window on screen, for example a method to show a list of characters:
ShowCharactersTable(List<Character>list,
Action<Character>didSelectCharacter, Action<bool>didCancel)
Example in use:
ShowCharactersTable(someList, delegate(Character selectedCharacter) {
// code that runs after you picked a character
, delegate(bool didCancel){
// code that runs after you cancelled selection
});
This is fine. Everything is transparent and easy to use. But I get into trouble as soon as I need to nest this. For example, on character list I have few buttons on each character cell, so I need to provide delegates for that. This gets complicated. I also might need to show another modal window on top of that, with a call like this:
ShowActivitySelector(List<Activity>activitiesToShow,
Action<Activity>didSelectActivity,
Action<bool>didCancelPickingActivity);
And when I select activity I might need to show Alert if something goes wrong, like here:
ShowAlert(string alertText, Activity<bool>didAccept,
Activity<bool>didCancel);
So now, to call a simple table of characters I need to write a 3 page long method with nested delegates. Does not sound like fun. How can I modularize this and make easier/more maintainable?
I don't want to couple my interface to my model, as I will need to show those lists, selectors and alerts from many different parts of my game with different parameters.
How can this be fixed and what do I do about this?
Related
This might sound weird, but I am just experimenting with the thought of it. I was wondering about subscribing functions to different classes. So i have a base or static location where my method is held, and without relying on inheritance, am i able to subscribe that function to an object?
For example:
Action class has a method class SendKeys
I have three objects called Textbox and Button and Textarea
Realistically i don't want them all to have access to SendKeys function, just Textbox, and Textarea. But i also don't want to copy paste the SendKeys code over and over again.
I could create a static class that takes the data and the two objects will call that static class, but that just seems like extra work and i would be creating the function anyways in order to call an external function.
The best solution i have is to just copy paste code. but i was wondering if i could subscribe specific functions. Its like the opposite of what an event and delegate can do right? Cause the subscription requires code in the class of the subscriber. I kind of think i want partial classes? I am not sure. Thoughts?
A deeper dive into the issue:
I have a bunch of different elements to work with here are some basic ones, it goes deeper when you take into account custom elements:
Button
Textbox
Textarea
MultiSelect
SingleSelect
RadioButtons
Checkboxes
MenuItems
PasswordTextboxes
ETC
Each one of these would have their own actions that can be applied. For example they all would have the same properties like GetAttribute or GetCssValue but i don't want to be sending keys to a checkbox, so i dont want to have the ability to have that function when creating inheritance. BUT, i do want other objects to have those functions. The code is lengthy and a bunch of copy pasting code is ugly. I was hoping i can subscribe functnions to objects. So i can say something like Actions.Click(Textbox) or Textbox.Click or w.e but i cannot do Actions.SendKeys(button, "fdsaf") or Button.SendKeys("fdsaf")
I've been wondering a lot how to have an object act different situationally.
To clarify what I'm wondering:
I want to make a menusystem, and I want to have a "button" class. But the button should behave different depending on what kind of button it is.
One button may close to program, another may start the game, a third may enter settings.
(I was thinking of parsing methods as arguments, but then you still have to write a lot of different methods somewhere in your code)
How do you do this with OOP in mind? I could hardcode the very basic functions of a simple menu using enums and switchcases, but I would want to know if it could be avoided.
I want to avoid things like delegates because games aren't eventbased in such fashion, and also switch-cases, large if/else statements because they are really ugly.
Is there a way to make objects behave like this?
What are other alternatives to making menus, trying to avoid the switch-cases for the commonly used enum. (Not disallowing enums)
I want to avoid things like delegates because games aren't eventbased in such fashion
Aren't they, though? A button click is an event, regardless of whether or not it's a game or a web application. It's by definition something happening that you'd like to react to, such as a button press. What happens when a button is clicked should be loosely coupled from the button in the UI, for the reasons you already encountered (large switch/if-elses are a pain) among others. A C# event field seems like the perfect fit, for this particular case anyway.
At some point, you create the settings button, somewhere, somehow. Why not wire up the event there? Something along the lines of:
class Button
{
public Button(string label) {}
public event Action Clicked;
}
class Program
{
public static void Main(string[] args)
{
var settingsButton = new Button("Settings");
settingsButton.Clicked += () =>
{
// open settings view
};
}
}
I'd avoid things like inheritance for this problem as it adds unnecessary complexity for the wrong reasons. You should (probably) use inheritance if the overriding class changes or supplements the behavior of the class it extends (a logical progression would be object extended by Component extended by Button extended by ToggleButton) but not to create a class hierarchy that's very much tied to how your UI is built up. If you change settings access to a dropdown menu instead of a button press, you don't want to be tied to a SettingsButton class; you want to be simply able to change which event triggers the desired behavior, in this case pulling down the dropdown menu.
I have written a C# 4.0 Windows Forms Application that creates two panels which are both populated exclusively with text labels. I would like to add functionality to my application to print these panels exactly as they appear on the form, but I only want to print these panels and their contents, with no background or other parts of the form.
This link was especially helpful as an overview, but so far I'm only able to print what amounts to a screen capture of the form. The entire form is included, buttons, trim, background, and all. It looks like I need to "rebuild" the form by creating a graphics object (I use the term generically, as I'm not sure what specific graphics-related class I need to employ) and somehow transfer the contents of the panel into this object.
My question is: what classes and/or methods should I research in order to build this graphical object? Also helpful to know: are there any handy tricks within the .NET framework or any libraries out there to automatically fit the result to a single page when building the PrintDocument object?
OK, I found one way to do it (love to my Perl bros out there):
Wrap both panels in another parent Panel. Let's call this Panel "parentPanel." Create a bitmap (memoryBitmap)that is the size of parentPanel (parentPanel.Size).
Next: parentPanel.DrawToBitmap(memoryBitmap, new Rectangle(parentPanel.Location, parentPanel.Size)
Then, in the print page event handler: e.Graphics.DrawImage(memoryBitmap, 0, 0)
I'll leave this open in the likely event that someone else has a better idea.
Currently my main form has a ton of event handlers because there are a lot of controls. It is very similar to a paint application. I have condensed it down quite a bit and I am sharing event handlers whenever possible but the class is still around 1,000 lines of code. I realize that may not be much to all of you but it is considerably larger than the rest of my classes.
I have refactored a lot of code to other classes but all those event handlers still increase the line count by a large amount. I also started using region blocks to separate event handlers in to groups and that is working rather well but I still would like to know SO's opinion on the matter as to best organize a large amount of form event handlers.
Edit: So I've been using partial classes and I must say, I don't really like them that much. I'm not sure what to do at this point.
I may go back to using region blocks as I'm not sure user controls will help my problem at all. Honestly I did not mind the region blocks that much. That class was the only place I used them and it organized the different sections of the code quite nicely (Menu Event Handlers, Toolstrip Event Handlers, Drag and Drop Support, et cetera).
Still, if anyone still has any other ideas or would like to elaborate upon any posted thus far I'd be more than appreciative as I am still looking for a better solution to this problem.
1000 lines of code is nothing, and that should not be the basis for refactoring your code. Refactor your code where it makes sense; not just because a class contains more lines of code than your other classes. Some classes will require more code than others, and that's perfectly okay.
That being said, if it makes sense you can divide the controls into logical sections, and put them in user controls. Make sure that there is a good justification for doing so though, because otherwise you'll only be convoluding your code base.
I must remind you again though, don't split your code up just to reduce the lines of code.
You could either split the functionality into separate classes (e.g. creating UserControls like Ed has suggested), or think about using partial classes (where one class can be split among many files). I have found partial classes handy to group together related chunks of code, when the "main" class file is getting to large. Sometimes this is the first step in refactoring those chunks of code into separate classes and/or controls.
It's hard to make a concrete recommendation without seeing the code, but those are some of your options.
If you haven't already (you don't mention it) I would split out the various individual controls into UserControls. You can handle all of the events from within the UserControl class and only expose those events that the parent form must absolutely handle. These will likely be small in number and will drastically reduce the responsibilities of your main form.
For example, each tool button could live inside of a UserControl. The canvas control can maintain and instance of the tools control and so on. You can keep creating the composite controls where each upper layer becomes less complicated and most of the actual logic is handled below it.
I would suggest of using more OOP solution. Do not add UserControls, as you add more *complexity*. Let's try to maintain complexity you already have, but make things more clear, cause this is what really you're asking for, I believe.
DI like. In practise if you need to handle a lot of events for a lot of contorls, create ControlManagers, which accepts in ctor the control and subscribes to its events.
So for every control you will have it's own manager.
Advantages:
Clear separated code in different classe, so easy recognizable in case of problems and my be more clear from architectural point of view.
You don't break down your architecture with a lot ot delegated events between tons of controls and subcribers (one subscriber per control)
Sure you will need organise, by the way, the data flow between different classes. But it's by my experience, haven't to be a big problem.
EDIT
An example pseudocode:
UserControl1 mycontrol1; UserControl2 mycontrol2;
public class MyControl1Manager {
public MyControl1ManagerFor1 (UserControl1 uc1) {
//subscribe to events of uc
// here all code to handle events
}
public MyControl1ManagerFor2 (UserControl2 uc2) {
//subscribe to events of uc
// here all code to handle events
}
}
and somewhere in code:
MyControl1ManagerFor1 controlManager1 = new MyControl1ManagerFor1 (mycontrol1);
MyControl1ManagerFor2 controlManager2 = new MyControl1ManagerFor2 (mycontrol2);
Something like this.
Hope this helps.
Once I had a form that became really big. It showed the same information in many various ways. To reduce number of code in single file I used an approach similar to UserControls. All the GUI elements were placed on the form, but their initialization and handlers were maintained by helper classes. They were equivalents of UserControls, but without GUI interface. These classes were initialized in main form's constructor:
SideViewHelper sideView = new SideViewHelper(parentForm, gridControlMaster, gridControlDetail, buttonSubmit);
All the logic that handles the gridControl events, button events are handled inside the helper class.
After the initialization the main form (parentForm) may change state of many UI items by single call of ViewHelper's method.
These classes are created for this only form and are as lightweight as possible.
How can I create a Delphi TSpeedButton or SpeedButton in C# 2.0?
Using a Button and setting the TabStop property to false only works when tapping through the form...
If you need (as I did) a button that does not get selected when clicking on it, there is only one way I have found to do it.
The way I did it, was to subclass the Button class and in the constructor calling the SetStyles and thereby setting Selectable to false, like so:
public class ButtonNoFocus : Button
{
public ButtonNoFocus()
: base()
{
base.SetStyle(ControlStyles.Selectable, false);
}
}
This worked out for me, and is perfect if you e.g. have a control-panel with buttons that perform actions to a selected object...
I'm wondering if you want to create a control like a TSpeedButton, or you just need same kind of end result ...
Programming one from scratch is certainly possible, but I'd only tackle that as a learning exercise.
Assuming you want to achieve a similar end result ...
Delphi's TSpeedButton had a differences from the standard TButton that developers found useful - it was flat, didn't take focus, and it consumed fewer resources than a regular button (because it didn't have an underlying Windows Handle).
Which of these are important to you?
If you just want a flat button that doesn't accept focus, use a regular Button with FlatStyle=Flat (or PopUp) and TabStop=false. You can configure a glyph by setting either the Image property, or a combination of ImageList and ImageIndex/ImageKey.
An alternative to this would be to look for an existing button component that comes close to your needs - one place to look might be the Krypton Toolkit (free to use, see http://www.componentfactory.com/toolkit_buttoncontrols.php).
If you're wanting to reduce the number of resources consumed by your application, it's likely you'll get a better return looking elsewhere.
Back in the days of Windows 3.1 (Delphi 1) and Windows 95 (Delphi 2), the number of available handles was strictly limited, with a maximum number available system wide. Today, with Windows XP and Vista, the number of available handles is far far higher, and the number is per process, not system wide. Unless you're creating thousands upon thousands of buttons, you're very unlikely to come anywhere close to running out.
Does this help? Looks like you would have to handle the OnPaint event, and not take focus...
The regular .net 2.0 button supports part of what a TSpeedbutton Does:
The Glyph: Image
Flat : FlatStyle
It does not handle:
Down
Group
These two are related, you could inherit from the button, and ownerdraw it, adding Down and Group features.
Codeproject has an example of ownerdraw buttons.