WinForms and child forms - How to consolidate redundant "utility" code? - winforms

I searched and Googled first, thinking surely someone must have asked this before, but I sure can't find a good description of this problem.
I have six or eight similar C# .NET 2.0 WinForms applications built with the fairly common model of a main application window with several GUI data fields plus several modal dialogs for further data collection. Many of the data fields (especially TextBoxes) have identical data validation routines. I'm writing the same xxx_Validating() routines over and over, which in the simplest case only capitalize the first character of the entered text (if any) and redisplay the result. I have another one for ZIP Code fields that takes the first 3 digits of a 5-digit US postal ZIP Code and returns the corresponding State, using a 1000-member string array. Simple stuff. There are a few others; here's an example:
public void CapFirstCharTextBox_Validating(object sender, CancelEventArgs e)
{
string strValue = ((TextBox)sender).Text.Trim();
if (strValue.Length >= 1) {
if (char.IsLower(strValue[0])) {
strValue = strValue.Substring(0, 1).ToUpper() + strValue.Substring(1);
((TextBox)sender).Text = strValue; // fires (whatever sender)_TextChanged()
}
}
}
Again this is part of a half-dozen or so such "utility" routines. I've only got one set of these per dialog box class, and all the various TextBoxes in that dialog which need this have their Validating event pointing to the same method. So it's not like I've got 20 of these in a given source file (one for each TextBox) or anything; there's only one for the whole dialog class.
Problem is, the whole set of these exists in every source file where I need them. That's one set for the main window and more for each pop-up dialog box -- and that's too many. I understand modal dialog box classes can't communicate with each other, and making all this stuff global is elusive at best and a big "no-no" at worst.
I have successfully tried passing a reference to "FormMain" (where one copy of these routines exist) to the various dialog constructors, and then calling these validation routines with that from their own validation handlers. It works but feels awfully clunky and certainly not like the best approach.
So, how would I (or would I want to) rearrange the project and organize the code better to have only a single instance of these kinds of things? How would I wire up a global "utility" class of such methods such that I can get to it from the main form's code and from that of a bunch of pop-up modal dialog boxes as well?
I'd like to maintain just one executable with no additional .DLLs if possible (these are all one-project-per-solution, by the way), and if practical I'd like to further be able to share that common code across multiple solutions.
I think the answer will include writing new assemblies, using different namespaces (currently all my code in a given project is contained in the same namespace), and maybe separating this stuff out into its own project in the same solution file.
Is it possible?

You can share code across solutions by keeping the code in one place and adding a link to the file in each solution.
To add a link: right click the project (or folder) you want to add the code to, then select "Add existing item", browse for the file, when found click the down arrow on the button and pick Link to.
This way the projects that link to the file will share the same code.
BTW: take care when using a source control system that doesn't know how to handle these links.

Related

How does XML document work with GTK to create user interface?

I am working on a C/GTK+3 project right now. I have a little experience with front end but mostly only with Android. Even then that was VERY LITTLE experience.
I notice that in the C code I place objects and set properties (like if a textview is editable etc). I also have been able to connect a .ui XML file to my program with the builder functions.
I am wondering how the XML file gets linked to the C code defining the interface. Does it match by structure, by the name or ID properties? Why are properties like "visible" and "editable" present in both the C code and the XML? Do you need the XML file? Do you need to specify the properties in both the XML file and the C code or just one? Will I ever completely understand front end development?
There's two ways of constructing a user interface:
You write the code for it.
You write a file that describes the user interface, and have the user interface built for you at runtime.
If you write the code yourself, everytime you want to move widgets around, you have to modify your code, that you'll need to compile. That is doable for a small UI, and is what is done in most tutorials.
If you use ui files, then you use the Glade application to design your UI graphically, and it will write the UI files for you. This helps in splitting responsabilities too: you may have design people taking care of the UI, and let developpers focus on the behavior. Even without that, you'll be able to design a UI faster with an editor like Glade than by coding it by hand. Think you skip all the compile/debug cycles.
In your ui file, if you name a wigdet "bob", you'll be able to get it in your code by passing its name to gtk_builder_get_object. GtkBuilder takes care of the construction and the memory, so don't destroy the widgets it creates if you need to display them again, and hide them instead.
You have examples of use of UI files in the GTK documentation:
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.5

Converting multiple (and different) windows into tabs

Fairly new to WPF.
I'm tasked with converting our application with about ten different windows into a single-window, multi-tabbed application. I'd like your input on the most effective way of doing this.
I suppose I could do this the most-straightforward way -- copying and pasting a ton of code into the main XAML file. I imagine I'd end up with a gigantic file though, and would like to avoid that.
I should mention that the contents of each tab will be substantially different from each other.
There must be some element of WPF that enables this that I just haven't been able to find. Really appreciate any input.
In XAML there are user controls which you can use. That way, you could use one user-control per tab-content and let the main window only contain the tabview and tabitems and some minor logic code.
To achieve that, you can simply copy-paste most of your current window-code in one user control per window. The code base could remain almost the same (if there are no interactions between the windows at least).
There are quite many resources out there containing further details on user controls like this code-project article (a bit old, but the majority of its contents will still apply) or that MSDN one.

WinForms MenuStrip Isolation to improve Code Maintainability

In Windows Forms, C#, .NET 3.5, VS2008...
What's a good way to isolate the code for a MenuStrip (or any complex control group), and it's child menu items, from the rest of my form?
For example, when I have a MenuStrip with a number of menus and each menu has a number of menu items, which all have click events, a ton of code is spewed into both the Form.Desinger.cs file and also the Form.cs file. This is not causing any problems technically, but just feels wrong to have so much stuff all dumped in one place (along with everything else in the form).
Running the Code Metrics on my entire project, the form is flagged as having the worst Maintainability index of any project file. Normally, I'd not be too dogmatic about heeding the direction of the Code Metrics tool, but in this case I totally agree.
According to Code Metrics, the form violates these best practices:
Too much class coupling
Too many lines of code
Overall low maintainability
Possible solutions to isolate the MenuStrip from the rest of the form:
Stuff it into a UserControl
Other ideas?
I think you should take care about isolate business logic from presentation logic, for instance does not place too much code in click handlers or implement commands for menu items.
Get sure your code metrics does not touch generated code or don't pay attention to bad metrics in autogenerated code.
Can you disable or filter your CodeMetrics from grabbing *.Designer.cs, for example?
If not, I would use a Factory class so that you can create these structures in one line. The down side to this, is that it reduces the functionality of the Designer. In the factory, you could name each component based on a template string + "_FileMenu", for example, so that you could set the base "name" in the Factory constructor.
To reduce code spew in your Form.cs file, consider more of a MVC approach, so that when the designer generates, say a private void button1_Click method, you abstract some business logic to other methods of other classes. So instead of moving all your files, button1_Click will call InitiateMoveFileMethod( string source, string destination ), for example.

Complex .Net 2.0 Windows Forms control: where to start?

In order to make a convenient UI for an .Net 2.0 Winforms application I am working on, I have need for a control that I'm pretty sure goes beyond the "out of the box" behavior of any standard control. A mock-up of what I'm trying to achieve follows:
Mock up http://www.claware.com/images/temp/mockup.png
Essentially, this part of the application attempts to parse words into syllables from tribal languages (no dictionary to refer to; any and all unicode characters are possible.) By the time the user gets this far, he has already defined the vowels / consonants in his language and some other configuration. There is then an iterative process of (1) the application guesses which syllables exist in the language based on some rules, (2) the user refines the guesses, selecting the correct parsings or manually parsing a word, (3) the application "learns" from the user's feedback and makes smarter guesses, (4) repeat until the data is "good enough" to move on.
The control needs to present each word (the grey headers), then all the syllable break guesses (the white areas with dots separating the parts of words.) There is also a way to manually enter a parsing, which will display a text area and save button (at the bottom of the mockup.) When the user hovers over a guess, the background changes and "accept / reject" buttons appear. Clicking on the accept, or entering a manual parsing, removes the entire word from the list. Clicking the reject button removes just that item.
I'm by no means 100% sold on the formatting I have above, but I think you can get a general idea of the types of formatting and functional control I need. The control will also scroll vertically--there may be thousands of words initially.
My question for you experienced WinForms developers is: where to start? I would really, really like to stay within the .Net core framework and extend an existing control as opposed to a third-party control. (At the risk of starting a religious war: yes, I suffer from NIH-syndrome, but it's a conscious decision based on a lot of quick-fix solutions but long-term problems with 3rd party controls.) Where can I get the most "bang for my bucK" and the least reinventing the wheel? ListView? ListBox? ScrollableControl? Do I need to go all the way back to Control and paint everything manually? I appreciate any help that could be provided!
[Edit] Thanks everyone for the ideas. It seems like the most elegant solution for my purposes is to create a custom control consisting of a FlowLayoutPanel and a VScrollBar. The FlowLayoutPanel can contain instances of the custom controls used for each word. But the FlowLayoutPanel is virtual, i.e. it only contains those instances which are visible (and some "just out of scroll"). The VScrollBar events determine what needs to be loaded. A bit of code to write, but isn't too bad and seems to work well.
I would look at the TableLayoutPanel and FlowLayoutPanel controls. These will let you organize a series of controls with moderate ease in a vertical fashion. I would then create a UserControl that consists of a label and 2 buttons. The UserControl will expose properties like Text and events that are exposed for the button clicks.. For each entry in the list, you will create an instance of the UserControl, assign the text value, and handle the click events. The instance will be placed in the Table/Flow panel in the correct order. Both of those layout panels do allow for inserting items between other items so you can add/remove items from the list dynamically.
Edit:
Given the length of what you are trying to render, I would consider using the DataGridView and do some custom rendering to make it perform how you want it to work. Using the rendering events of the DGV you can merge columns, change background colors (like highlighting the dark gray lines), turn on/off the buttons, and handle changing the grid into edit mode for your rows to allow modification or inserting of new values. This method would easily handle large datasets and you could bind directly to them very easily.
Well, this certainly looks like a candidate for a custom component that you should be creating yourself. You can create this using standard .Net drawing commands along with a text-box, and a regular button control.
Now you want to find out where to start.
Create a Windows Forms Control Library project.
Drop in the textbox and the button control.
The panel drawing code should preferably be done by code. This can be done using the regular GDI+ commands.
Edit:
Here's another idea, and one that I've practically used in my own project with great success.
You could use a web-browser control in the app, and show your data as html. You could update the source of the web-browser control based on the input in the textbox, and clicking on the links in the web browser control will give you the event that you can trap to do some action. Your CSS will work.
I used this technique to build the 'desktop' in an app I made called 'Correct Accounting Software'. People loved the desktop so much that it is one of the best loved features of the app.
Here's how I would do it:
Create a custom control. In this custom control, have a ListBox atop a LinkButton, and when the LinkButton is clicked you can make it give way to a TextBox. The ListBoxes will have the top row unselectable... you can probably get the rest from there. When you get your list of words, fill a Scrollable of some kind with one control for each word:
(foreach String word in words){
myScrollable.add(new MyComponent(word));
}
From there, I'm not sure what you want to do with the boxes or the data, but that's my initial idea on the UI setup.
Use the WebBrowser control and generate the HTML markup into it using DocumentStream or DocumentText.

Best place to bring up new window in Model View ViewModel

I have an MVVM application. In one of the ViewModels is the 'FindFilesCommand' which populates an ObservableCollection. I then implement a 'RemoveFilesCommand' in the same ViewModel. This command then brings up a window to get some more user input.
Where/what is the best way to do this whilst keeping with the MVVM paradigm? Somehow
doing:
new WhateverWindow( ).Show( )
in the ViewModel seems wrong.
Cheers,
Steve
I personally look at this scenario as one where the main window view model wants to surface a task for the end user to complete.
It should be responsible for creating the task, and initializing it. The view should be responsible for creating and showing the child window, and using the task as the newly instantiated window's view model.
The task can be canceled or committed. It raises a notification when it is completed.
The window uses the notification to close itself. The parent view model uses the notification to do additional work once the task has committed if there is followup work.
I believe this is as close to the natural/intuitive thing people do with their code-behind approach, but refactored to split the UI-independent concerns into a view model, without introducing additional conceptual overhead such as services etc.
I have an implementation of this for Silverlight. See http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx for more details... I'd love to hear comments/further suggestions on this.
In the Southridge realty example of Jaime Rodriguez and Karl Shifflet, they are creating the window in the viewmodel, more specifically in the execute part of a bound command:
protected void OnShowDetails ( object param )
{
// DetailsWindow window = new DetailsWindow();
ListingDetailsWindow window = new ListingDetailsWindow();
window.DataContext = new ListingDetailsViewModel ( param as Listing, this.CurrentProfile ) ;
ViewManager.Current.ShowWindow(window, true);
}
Here is the link:
http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx
I guess thats not of a big problem. After all, the Viewmodel acts as the 'glue' between the view and the business layer/data layer, so imho it's normal to be coupled to the View (UI)...
Onyx (http://www.codeplex.com/wpfonyx) will provide a fairly nice solution for this. As an example, look at the ICommonDialogProvider service, which can be used from a ViewModel like this:
ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>();
IOpenFileDialog openDialog = provider.CreateOpenFileDialog();
// configure the IOpenFileDialog here... removed for brevity
openDialog.ShowDialog();
This is very similar to using the concrete OpenFileDialog, but is fully testable. The amount of decoupling you really need would be an implementation detail for you. For instance, in your case you may want a service that entirely hides the fact that you are using a dialog. Something along the lines of:
public interface IRemoveFiles
{
string[] GetFilesToRemove();
}
IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>();
string[] files = removeFiles.GetFilesToRemove();
You then have to ensure the View has an implementation for the IRemoveFiles service, for which there's several options available to you.
Onyx isn't ready for release yet, but the code is fully working and usable at the very least as a reference point. I hope to release stabilize the V1 interface very shortly, and will release as soon as we have decent documentation and samples.
I have run into this issue with MVVM as well. My first thought is to try to find a way to not use the dialog. Using WPF it is a lot easier to come up with a slicker way to do things than with a dialog.
When that is not possible, the best option seems to be to have the ViewModel call a Shared class to get the info from the user. The ViewModel should be completely unaware that a dialog is being shown.
So, as a simple example, if you needed the user to confirm a deletion, the ViewModel could call DialogHelper.ConfirmDeletion(), which would return a boolean of whether the user said yes or no. The actual showing of the dialog would be done in the Helper class.
For more advanced dialogs, returning lots of data, the helper method should return an object with all the info from the dialog in it.
I agree it is not the smoothest fit with the rest of MVVM, but I haven't found any better examples yet.
I'd have to say, Services are the way to go here.
The service interface provides a way of returning the data. Then the actual implementation of that service can show a dialog or whatever to get the information needed in the interface.
That way to test this you can mock the service interface in your tests, and the ViewModel is none the wiser. As far as the ViewModel is concerned, it asked a service for some information and it received what it needed.
What we are doing is somethng like that, what is described here:
http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx
The ViewModel has a property that is called ConfirmDeletionViewModel. As soon as I set the Property the Behavior opens the dialog (modal or not) and uses the ConfirmDeletionViewModel. In addition I am passing a delegate that is executed when the user wants to close the dialog. This is basically a delegate that sets the ConfirmDeletionViewModel property to null.
For Dialogs of this sort. I define it as a nested class of the FindFilesCommand. If the basic dialog used among many commands I define it in a module accessible to those commands and have the command configure the dialog accordingly.
The command objects are enough to show how the dialog is interacting with the rest of the software. In my own software the Command objects reside in their own libraries so dialog are hidden from the rest of the system.
To do anything fancier is overkill in my opinion. In addition trying to keep it at the highest level often involving creating a lot of extra interfaces and registration methods. It is a lot of coding for little gain.
Like with any framework slavish devotion will lead you down some strange alleyways. You need to use judgment to see if there are other techniques to use when you get a bad code smell. Again in my opinion dialogs should be tightly bound and defined next to the command that use them. That way five years later I can come back to that section of the code and see everything that command is dealing with.
Again in the few instances that a dialog is useful to multiple commands I define it in a module common to all of them. However in my software maybe 1 out of 20 dialogs is like this. The main exception being the file open/save dialog. If a dialog is used by dozens of commands then I would go the full route of defining a interface, creating a form to implement that interface and registering that form.
If Localization for international use is important to your application you will need to make sure you account for that with this scheme as all the forms are not in one module.

Resources