Every time I need to adjust AutoSize and/or AutoScroll in WinForms, it’s always a struggle to get things working and looking right. Hopefully this post will help me avoid this struggle the next time I have to do it.
To enable AutoScroll on a panel, AutoSize must be false. If the panel is contained within another panel, that panel’s AutoSize must also be false. If any of the panels are a TableLayoutPanel, the row containing the control that needs to AutoScroll must be set to Percent, 100. All controls within all of these panels must be set to Dock.Fill. Lastly, if adding controls dynamically to any of the panels, set them to Dock.Top.
Seems that more and more resources are sprouting up online for software developers, most of which are pretty basic courses. “Learn to code in Java”, “Create a website in 30 days”, “Android Development Basics”, and the like. Then there’s the university courses that allow you to earn college credit for cheap, or just audit the course for free. I’ve browsed a variety of these online resources, and my experience has been pretty mixed. Sometimes they help me, but other times I feel like a physical book is a much better choice.
Even within a single company, I find courses that I get a lot out of, and others that basically just waste my time. Pluralsight is one such company. I often see one of their course titles that interests me, but when I actually take the course it’s hit or miss whether or not it helps me out. I recently took a few SQL Server courses, but I didn’t get out of them what I was looking for. I was left feeling that my time would have been better spent reading books on the same topics.
My learning style may have a lot to do with whether or not online courses benefit me. For me, watching a course or listening to someone explain something isn’t enough for things to sink in. I like to see the big picture, play with things, and discover on my own how and why something works the way it does. Generally after I’ve spent some time in discovery, then I can watch someone else explain a topic and pick up on everything they’re saying.
Overall, physical books seem the best way for me to learn. With a book in front of me I can read something at the pace that I’m comfortable with, and if I think I missed something I can easily redirect my eyes to read it again. Then I can pause, think about what I’ve read, try it out on my computer, re-read it, reach an “aha” moment, then proceed on to the next section of the book.
I have a hard time doing the same with online resources, mainly because the controls are cumbersome. Sometimes I play the skip-forward, skip-back game, wasting time trying to find the spot that I need to get back to. Then by the time I find it, I’ve lost my context. I also find that most online instructors rush to get to the next section of the video. I don’t know if they’re on a strict time budget, if they’re concerned about keeping their audience’s attention, or what. The courses that benefit me the most are the ones that take time to explain the same concepts in different ways before moving on.
Those are just some of my thoughts regarding online developer resources. I’d love to hear other developers’ experiences though.
Which online resources have you tried?
Which online resources worked best for you?
Do you generally learn more from books or from videos?
Have you paid for courses that turned out to be a bust?
Are your choices dictated by your learning style, or can you adapt to any resource?
Are there particular resources out there that mesh well with multiple learning styles?
Have you taken any courses that should charge an arm and a leg because they’re so good?
This post is a little self-serving, as I might be the only one who needs to know this in the future, but I’m sure I’ll forget all about this some day when I google this problem and find the answer in my own post.
Today I needed to use an image that was in one VS2010 project in a control of another project in the same solution. While you can certainly copy and paste the image into both resource files, I found a way that I can share the same file.
Step 1: Right-click the project you want the image in and choose ‘Unload Project’ from the context menu.
Step 2: Right-click the project again and choose ‘Edit [project name].csproj’.
Step 3: Find a <ItemGroup> section and insert the following code into it:
,EmbeddedResource Include="..\[project name]\Properties\Resources.resx"> <Link>[assembly name].Properties.Resources.resx</Link> <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>[assembly name].Properties.Resources.Designer.cs</LastGenOutput> <CustomToolNamespace>[assembly name].Properties</CustomToolNamespace> </EmbeddedResource>
Replace “[project name]” with the actual name of the project that contains the resource file of the image you want to use.
Replace “[assembly name]” with the actual name of the assembly for the project.
Step 4: Right-click the project and choose ‘Reload Project’. If prompted, allow VS to close the .csproj file.
Step 5: When you bring up the Image picker dialog for the control, you’ll now have the new resource file to choose from in the dropdown menu:
For anyone who is a C# programmer, or wants to be a C# programmer, or was a C# programmer and needs a refresher, this is the best reference I have ever read. Sean is practical, succinct, and humorous. I’ve linked to his first post of the series. He has other blogs that I will also be checking out.
When I started using Windows 8 I didn’t expect to have issues with being able to organize things the way I want to. At the risk of sounding crotchety and inflexible, I must say that the Windows 7 experience was near perfect and the Windows 8 experience is ridiculous.
In Windows 7 whenever I needed an application, I would browse the programs from the start menu. For me, the layout was natural. I knew what folders looked like. They were manila and rectangular with a tab at the top. They’ve looked that way for all my life. If the application was a standalone one, I would look for it outside of a folder. If it was part of a suite, I would look for a folder by the name of the suite. They were arranged vertically, so I could easily see the length of each name. If I was looking for “paint.net”, then I could easily scroll down to the p’s and look for a short entry. It was quick and painless.
In Windows 7 if I used something like paint.net on a regular basis, I could pin it to the start menu. If it was the only “p” on the start menu, then I could hit the Windows key, then the “P” key, and it would start up. Simple, easy, painless. Okay, in this case I lied a little. “Programs” starts with “p”, so I would actually have to hit the Windows key, then the “P” key, then the “Enter” key. But for most applications it was one key shorter.
Enter Windows 8. Now the Windows key brings me to a butt-ugly assortment of live tile garbage that hurts my brain to look at. I have to search for a tiny little arrow to access the things that I do care to look at, a poor replacement of the programs list – “Apps”.
By default, Windows 8 apps claim to be organized by name, which would be decent if it was true. In reality, some apps are organized by name, and others are organized by category. Gone is the concept of folders, and everything has a colorful image next to it that makes me feel like I’m in CandyLand. The images are so small that they are practically meaningless. I need to read the text next to it to decipher what it is. The organization can be changed to “By Date Installed”, which is useless, or “By Most Used”, which makes everything I use infrequently impossible to find. I’ve changed my app organization to “By Category”, which is somewhat better than the alternatives, but its visual layout and CandyLand icons still cause my head to hurt.
Apps are still arranged vertically, but they now wrap to multiple columns with no logical separation. If the text is too long, it gets truncated so Windows can cram more columns onto the screen. This results in unintelligible entries such as “Download Microsoft SQL Server C…”. What is this app going to do for me? I’ve never bothered to waste my time finding out.
Categories are simply plain text above the apps, which makes them almost invisible. There is no way to hide categories that I’m not interested in. Tell me, honestly, do I need to see all 50 applications contained in Microsoft SQL Server and Visual Studio every time I look at my apps? No. There is no way to remove an app from the list without uninstalling it. Why should I have to look at “Microsoft Web Platform Installer” every time I open the apps screen? I have never used it, and I never will. Same goes for “Windows Media Center”, “Windows Media Player”, and about 100 other apps.
Pinning apps to the start menu now means creating a live tile. I have chosen to bypass the live tile screen because it is absolutely worthless to me. So now, the best alternative I’ve come up with is to pin apps to my taskbar. It’s not ideal, because I generally like having a clutter-free taskbar. Another alternative is creating a shortcut on the desktop. Yeah, that’s not going to happen. The only thing I hate more than a cluttered taskbar is a cluttered desktop.
Some people have suggested using the global search instead of the live tiles or apps screens. Okay, let’s go down that path for a minute. Now instead of hitting the Windows key, then hitting a single character key to immediately access the app I want, I now need to type multiple characters, wait for Windows to think for a bit, watch it present me with some valid results and some garbage, then arrow down or use my mouse to select what I hope is the app I was looking for. Yeah, that’s much better!
Microsoft, you really piss me off with this release. It’s undeniably a step back for PC users. I understand why you did it though. It’s for tablet users. That’s fine. How much of the market is using Windows tablets? Roughly 16%. PCs running Windows are roughly 80%. Sure, it definitely makes sense to replace the PC experience with something optimized for tablets at this time. Definitely! Keep up the good work. We don’t need a PC Windows experience anymore.
I attended a user interface training event today from DevExpress, after which I highly recommend UI design training for every developer. Whether you create business applications, web sites, web applications, tablet or phone apps, or whatever, if you have a screen that your users interact with, you should care how well your information is presented on that screen.
Within my company, I can already identify some areas of improvement. I was initially blown away by the speed, capability, and flexibility of our product, as well as the design and elegance of the code it runs on. I am still extremely impressed with it, but I have occasionally found the usability of our UI lacking. Little things like the placement of buttons, the emphasis given to controls on the screen, and the use (or lack of use) of whitespace all make a difference in the usability of an application.
For years I have been intimidated when it came to user interface design. I have thought to myself, and have said out loud that “I am not artistic, so I shouldn’t be a designer.” One problem with that thinking is, as a developer in today’s environment, visual design of an application is inescapable. Chances are that you cannot get away with strictly creating web services, OS services, or simple console applications that perform work in the background. If there are such programming jobs available, they’ve probably been filled already, and the people filling them probably have no intention of giving their seats up. The alternative, then, is to realize that you are creating user interfaces already, whether you like it or not, and to create them the best that you can.
As I learn more about UI design throughout my career, I realize that it is actually less of an art and more of a science. In fact, the more artistic the UI, the greater its chances are of reduced usability. Over the past few years I have become increasingly intrigued by the biology and science of User Interface design. I also seem to have a knack for identifying usable and poor designs. This new perspective helps me to realize that just because I am not artistic doesn’t mean I can’t create well designed user interfaces.
I have learned a couple quite interesting things (to me at least) over the past couple days:
1) When a .NET DataGridView is bound to a view and new unbound columns are dynamically added to it, it does not support native sorting on the unbound columns. This was not necessarily a shocker, however it led to the second interesting thing I learned.
2) Custom sorting in a .NET DataGridView can not only be performed via native properties of a datasource object, but can also be implemented on dynamic collections within the datasource object.
Here is the setup of the problem I had to solve:
A Windows Form containing a .NET DataGridView was bound to a custom view which supports custom sorting and filtering through generics. The generic type we used in the view had 5 predefined properties, and a “property bag” object which used a dictionary collection to store additional properties. The types of properties stored in the property bag varied based on the type of records being displayed. To keep data sparsity low both in the database and in the front-end, it made sense to leave these properties dynamic and not make them static members of the class. Over time, however, our users wanted to see specific property bag properties as if they were native properties to the class. These properties would have to be dynmically added to the form’s DataGridView and support sorting, filtering, and exporting just as if they were static members.
My first attempt at a solution was to dynamically add columns for the additional properties, set the DataGridView’s VirtualMode to true, and handle the CellValueNeeded event to populate the data for the added columns. This didn’t prove to be enough though because the DataGridView did not support automatic sorting for the dynamically added columns.
At this point, I took a detour to determine if dynamically building a standard DataView to bind the DataGridView to would be a better solution. It proved to be a reasonable solution that didn’t require much custom coding, but it caused a couple other issues. Some functions of the form were designed to use the custom view and its collection of generic objects. To work around this, I stored the generic objects in a new column of the DataView without exposing the new column to the DataGridView so I could still access them in the other functions of the code that needed them. This caused performance problems though, due to creating and maintaining two representations of the same data in memory. For this reasons, I turned back to the first solution and dug into what it would take to implement custom sorting on the added columns.
The MSDN article here was quite helpful in explaining how to do a fairly simple custom sort. However, what I was going to need required much more complexity. Not only were the added properties unavailable at design time, but the way our custom view performed sorting was through a delegate function. I had already learned how to add the properties dynamically, but the delegate function would also need to be created dynamically.
Luckily, I found that this particular problem had largely already been solved by one of my coworkers in another area of the application. I copied his code and modified it to fit my situation. To keep the delegate function tied to the column it belonged to, I stored it in the column’s “Tag” property.
When I got the custom sort implemented and started testing it, I ran into an unexpected behavior. Apparently, when creating a delegate dynamically, any part of the delegate that uses a reference variable will store the value of the variable in the function. In my case, this was a problem because I used a reference variable for the name of the column within a foreach loop, which changed the variable’s value with each iteration. The end result was that each time the delegate function was called, it sorted the last added column instead of the column that needed to be sorted. The final step in implementing the custom sort (correctly) was to replace the reference variable with an instance variable. I used the column object’s “DataPropertyName” property instead, and then the sort worked like a charm.
In the end, I learned that the DataGridView is much more flexible than I ever knew. Not only does it offer several choices for presenting and working with data using standard DataTables and DataViews, but it was also designed to work very well with custom implementations. Kudos to the Microsoft engineers that designed it to work so well! On the other hand, I’m not quite as pleased that delegate functions can change their behavior when combined with reference variables.