Working with Objects with the Window Form DataGridView

If you're using the Windows Forms DataGridView and loading data into columns by pulling that data out of properties on objects, you should know that there's an easier way. Just create a List of your objects and use that List to set the DataGridView's DataSource property. The DataGridView will generate a row for each object in the collection and column for each property on the class. Typical code would look like this:

Me.DataGridView1.DataSource = ListOfObjects

Of course, the objects you're putting in the DataGridView may have properties you don't want to display. You'll also want to control the left-to-right order that the properties are displayed in. To take control of the DataGridView's columns, select the Columns property in the Properties window and click on the builder button that appears (that's the button with the three little dots). That will bring up the Edit Columns dialog, where you can add columns to the grid and decide which property each column will display.

In code, you'll also need to set the AutoGenerateColumns property to false to prevent the DataGridView from adding all of your object's properties to the grid anyway:

Me.DataGridView1.AutoGenerateColumns = False

Generating the rows in the DataGridView from a list of objects also makes it easy to retrieve the object associated with each row. You don't pull the data from a row's columns and use those values to recreate the object; instead, you can just pull the object from the row's DataBoundItem property. This code processes all the objects for the rows that the user selected:

For Each row As DataGridViewRow In DataGridView.SelectedRows
  Dim obj As MyObject = CType(row.DataBoundItem, MyObject)
  '…process MyObject
Next

Posted by Peter Vogel on 09/03/2013 at 7:13 AM0 comments


Free Tool: SharePoint Content Deployment Wizard

You know that when it comes to deploying your latest SharePoint solution, it's not enough just to move over your code/list/templates/WebParts/etc. Often you need to have specific content in your production SharePoint site to support your new application. The SharePoint Content Deployment wizard helps you leverage the Content Migration API to generate a cmp file holding the content needed for your deployment.

You still, of course, have to set up the content in your test site (which you probably will have done as part of testing your application). But once you've done that, you can run the wizard to select and export the content you need to move to your production site as part of deploying your solution (and the content can be anything from a list to a site collection). On your production site, you run the wizard again to import the content.

The wizard is smart enough to pick up any dependencies that your content needs (new content types, for instance). It's not smart enough, however, to handle moving content across SharePoint versions, though, so don't think of this as a migration tool.

But, think! No more staying up late banging in the content to have it ready for when the users come in (or, worse, forgetting to put in the content and having your code blow up).

Posted by Peter Vogel on 08/28/2013 at 7:50 AM0 comments


Check for Changes Between Collections with SequenceMatch

You'd prefer not to execute any update code more often than you absolutely have to. If you only have one object to deal with, checking to see if an update is required is simple: retrieve the corresponding object from the database, check to see if the two objects have different values in their properties, and update the database only if there is a difference.

However, the problem is more complicated if you have a collection of objects to update in your application and in the database. With two collections, you can check for differences between the objects that appear in both collections. But you'll also need to check if the collections have missing or added objects. Fortunately, SequenceEqual can do all those checks for you, returning false if the two sequences don't have the same elements or if matching elements are different.

There are two wrinkles here, though. The first is that the two collections must be sorted the same way. This example sorts two collections by ID and then calls the SequenceEqual method on one collection, passing the other collection to determine if an update is required:

Dim usrs = (From cu In context.CompanyUsers
            Order By cu.ID
            Select cu).ToList
Dim updatedUsrs = (From us In ChangedUsers
                   Order By us.ID
                   Select us).ToList
If Not usrs.SequenceEqual(updatedUsrs) Then
    '…do update
End If

The second wrinkle requires some code. SequenceEqual doesn't actually compare the properties in the two objects: it just checks that the lists reference the same objects. If you've retrieved the objects from two sources (for example, if your application generated one set and the other set comes from your database), SequenceEqual will always return False. Fortunately, to get SequenceEqual to check the values of your object's properties you just need to have your classes implement the IEquatable interface, which I described in an earlier tip.

Posted by Peter Vogel on 08/08/2013 at 1:36 PM0 comments


Free Tool: Don't Reset Your CSS, Normalize It

Standards must be wonderful things; after all, there are so many of them. And there's a different standard for CSS defaults for every browser. As a result, if there's any relevant CSS setting that you don't supply a value for in your CSS, your perfectly good stylesheet will cause your page to display "uniquely" in every browser (and unique is never good).

The typical solution to this problem is to use a "CSS Reset" stylesheet, which shoves a value into every CSS setting (margins, line heights, font size) that might matter to you. But CSS Resets just steamrolls over the defaults, setting all numeric values to 0 or 1. It's a "zeroing out" approach. Since those "zeroed out" settings probably aren't what you want, you have to write a lot more CSS to provide values for those defaults.

Normalize.css takes a different approach. Rather than make every browser look like nothing, Normalize tries to make every browser look the same. Normalize.css attempts to support the browser defaults that are actually common, and bring those browsers that don't use those common defaults around to those defaults. So, for example, Normalize ensures that superscripts and subscripts use the same font-size and line-height in all browsers rather than zeroing those values out and forcing you to specify them. You can argue with the defaults the authors have chosen as "common," but they have drawn on the specifications established by a number of industry groups, including WHATWG (the people who brought you HTML5).

From a user interface design point of view, this is a two-edged sword. Users value consistency in their UIs more than anything else. Normalize.css will make your pages look alike across all browsers. But it also means that when your page is displayed in Chrome, your page may not look like every other Chrome page. I'm OK with that, but you're free to disagree.

Normalize.css is up to date with HTML5, understands mobile browsers, is easy to add to your project, and is well documented so that you know what it's doing (and why). It's not even very big. It should be the start point for all of your styling.

Posted by Peter Vogel on 07/30/2013 at 1:16 PM0 comments


Visual Studio Tip: Extend Your Most Recently Used List

The most recently used (MRU) lists on Visual Studio's menu list the last 10 projects (or files) that you worked on. However, I'm sometimes working on multiple projects for multiple clients simultaneously (please don't tell them: each one thinks they're exclusive). As a result, I have many projects on the go and often have trouble remembering which one I'm working on for any particular client.

Which leads me to Microsoft Office: One of the reasons I like the latest versions of Office is that they do a great job of showing me all the files and folders I've touched in the recent past. It's a great memory jogger because it isn't limited to the last 10 items.

You can't get those Office lists with Visual Studio, but you can extend your MRU lists to something more than 10: In Visual Studio, go to Tools | Options | Environment | General and set the "items shown in recently used lists" option to a higher number. Or, to a lower number if you'd prefer to forget about some of your recent projects.

Posted by Peter Vogel on 07/24/2013 at 1:16 PM0 comments


Control Testing for Equality with the IEquatable Interface

When you use the equals sign (=) or the Equals method to compare two objects, you're probably doing a reference comparison: You're asking if the two variables being compared are pointing to the same single object in memory. That may not be what you want.

What you may want is to compare two different instances of the same object to see if the two objects represent the same business entity. As an example, you might compare the variables Customer1 and Customer2, both of which point to Customer objects, to determine if both Customer objects represent the same customer. In that case, you want to do a value comparison: You want to ask if the two objects that the variables point to have identical values in their properties.

You can take control of that comparison in your custom classes by having them implement the IEquatable interface, which contains a single method called Equals. When code compares your object to another object of the same type, the Equals method will be called and be passed the other object. In the Equals method you just need to return False if any two properties on the objects are different. So, for a Customer object, an implementation might look like this:

Class Customer
    Implements IEquatable (Of Customer)

  Public Function Equals1(
        ByVal cust As Customer) _
        As Boolean _
        Implements IEquatable(Of Customer).Equals

   If cust.ID <> this.ID OrElse
      cust.FirstName <> this.FirstName OrElse
      cust.LastName <> this.LastName Then 
            Return False 
    End If 
    Return True 
  End Function 

End Class

However, the IEquatable interface version of the Equals method is used only when the variables are declared with the same data type (i.e., both variables are declared as Customer). If you compare a Customer to a variable of some other type (e.g., compare a variable declared as Customer to a variable declared as Object), then the base Equals method (the one that your class inherits from System.Object) will be used to compare the two objects. At that point, you're probably back to doing a reference comparison.

That behavior may be what you want: Customer to Customer comparisons will be value based and any other comparison will be reference based. But if you think developers using your objects may find this behavior inconsistent, you should also override the default Equals method and call your comparison code from that override also:

Public Function Equals1(
        ByVal cust As Customer) _
        As Boolean _
        Implements IEquatable(Of Customer).Equals
  Return MyValueComparison(CType(obj, Customer));
End Function

Public Overrides Function Equals(obj As Object) As Boolean
  Return MyValueComparison(CType(obj, Customer));
End Function

Public Function MyVallueComparison(cust As Customer) As Boolean
  If cust.ID <> this.ID OrElse
     cust.FirstName <> this.FirstName OrElse
     cust.LastName <> this.LastName Then 
       Return False 
  End If 
  Return True 
End Function

If you override the Equals method, you should override the GetHashCode method so that its results are consistent with the Equals method:

Public Overrides Function GetHashCode() As Integer
  Dim hash As Integer
  '…calculate hashcode and store in hash
  Return hash.GetHashCode()
End Function

You don't need to write a complicated GetHashCode method. The critical issue in overriding the GetHashCode method is to ensure that two objects that are the same (according to the Equals methods) return the same values from GetHashCode. It's not absolutely essential that two different objects return different values from GetHashCode. If your GetHashCode method always returns the same value, you'll have a "good enough" version.

The Dictionary object provides an example of how the value returned from GetHashCode is used. The Dictionary initially uses the hash code to reduce the time to find an object when searching by key. However, if two objects have the same hash code, the Dictionary falls back on the Equals method to find the right object. Using the Equals method will take the Dictionary longer than using the hash code, but you probably won't notice unless you have a lot of objects in the Dictionary.

Posted by Peter Vogel on 07/16/2013 at 9:59 AM0 comments


Selecting Items from a Collection using Another Collection with LINQ Joins

Here's the problem: you have a collection of objects with lots of information in those objects (the "rich" objects). You also have a collection of objects that represent a selection your user made in your application's UI (the "selected" objects). Unfortunately, your "selected" collection is a different and less useful set of objects; you really want to work with the "rich" objects. So Your problem is finding all the matching objects from the "rich" collection, based on the objects in the "selected" collection.

A LINQ Join solves the problem. Joining the two collections together gives you a new collection of the "rich" objects that have a matching item in the "selected" collection. In the LINQ statement's Join/On clause, you just need to specify the properties to be used to join the two collections together.

The following code joins an Entity Framework collection of all of the users in the company (CompanyUsers -- the rich objects) with a group of selected users from the UI (SelectedUsers -- the selected objects). The resulting collection holds just the rich objects:
Dim usrs = From cu In context.CompanyUsers
           Join id In SelectedUsers On cu.ID Equals id
           Select cu

Posted by Peter Vogel on 07/08/2013 at 1:16 PM0 comments


Use the Enum Object to Manipulate Enumerated Values

When it comes to writing Really Obvious Code, Enums are a tremendously easy way to make your code understandable. In the bad old days, when working on someone else's program I'd be forced to decode code like this:

Dim cust As New Customer
cust.Type = 0

With an Enum, everything is more obvious:

Dim cust As New Customer
cust.Type = CustomerTypes.Deadbeat

What takes Enums to the next level are the static methods built into the Enum class. For instance, if I want to turn an Enum into an array of strings, I can use the Enum class's GetNames method:

Dim cTypes As String() = [Enum].GetNames(GetType(CustomerTypes))

Because of the way Visual Basic handles names, Enum has to be enclosed in brackets to prevent syntax errors. C# doesn't require those brackets:

string[] cTypes = Enum.GetNames(typeof(CustomerTypes));

I can then bind the output from GetNames to any listing control to get a list of the names in the Enum displayed in my user interface:

MyListBox.ItemsSource = Enum.GetNames(typeof(CustomerTypes));

GetNames shows the basic structure of the Enum class's static methods: the first parameter to any method is always the Type of the Enum you want to work with. For instance, if you have code in a Web Service that's passed the value of an Enum, you can convert that value into the name of the corresponding Enum entry using the Enum class's GetName method. As before, the first parameter is the type of the Enum; the second parameter is the value you're looking up:

Dim inputValue As Integer = 1
Me.MyTextBox.Text = [Enum].GetName(GetType(CustomerTypes), inputValue)

Parse goes one better and converts a string containing one of the names in an Enum into the Enum item itself. This code, for instance, sets the Customer object's Type property to the appropriate Enum item based on a string value:

Dim custTypeString As String = "DeadBeat"
cust.Type = [Enum].Parse(
                GetType(CustomerTypes), custTypeString);

Visual Basic doesn't require the explicit cast to use Parse:

string custTypeString = "DeadBeat";
cust.Type = (CustomerTypes) Enum.Parse(
                typeof(CustomerTypes), custTypeString);

If the string value you're passing to Parse isn't an item in the Enum, the Parse method throws an exception. To avoid that, you can use the Enum's TryParse method which, while it still won't do the conversion, won't throw an exception either. An even better answer is to use the Enum's IsDefined method to see if the item exists before trying to retrieve it:

if (Enum.IsDefined(typeof(CustomersType), custTypeString))
{
  Customers ctype = (CustomersType) Enum.Parse(
typeof(CustomersType), custTypeString);
}
else
{
   ErrorLabel.Text = "Not a valid customer type.";
}

Posted by Peter Vogel on 06/28/2013 at 1:16 PM0 comments


Free Tool: CheckBoxList(For)

ASP.NET MVC's HtmlHelp has a TextBoxFor, a DropDownListFor, and even a HiddenFor method…but it doesn't have a CheckBoxListFor method. CheckBoxList(For) by Mikhail Tsennykh fills that gap and makes it easy to generate a list of checkboxes for an array of objects to let users can select which objects they want.

There are 16 overloads for Mikhail's CheckBoxList method, but the simplest version requires just five parameters:

  • The text to use for the select tag's name and id attributes
  • The list of objects to generate checkboxes for (you'll get one checkbox for each object)
  • The property whose value is returned to the server when the user selects that checkbox
  • The property whose value is displayed beside the checkbox in the page
  • The list of objects that should be shown as already checked

If you don't have any already selected items, you can get away with just the first four parameters.

Here's an example that displays a list of User objects, returns the User object's ID property to the controller, displays the User's name property beside the checkbox, and checks off those User objects that also appear in the collection called AlreadySelectedUsers:

@Html.CheckBoxList("Users",
                   Function(m) m.Users,
                   Function(u) u.ID,
                   Function(u) u.Name,
                   Function(m) m.AlreadySelectedUsers)

It's easy to switch between a horizontal or vertical list of checkboxes (the control even supports right-to-left reading order) and you can add on as many additional HTML attributes as you need.

At the controller, you'll get back a string array of the second parameter—one for each object whose checkbox the user checked in the browser. The controller method that would accept my sample CheckBoxList would look like this:

Function Change(usrDTO As UserDTO, Users As  String())
You can install CheckBoxList(For) through NuGet or download it from CodeProject (where you'll also find some documentation on how to use the extension and a sample application showing it in action). The method even attaches itself to the HtmlHelp control, where it belongs.

Posted by Peter Vogel on 06/21/2013 at 1:16 PM0 comments


Visual Studio Tip: Write a Property with Just a Name and a DataType

Sometimes auto-implemented properties won't do the job, and you need a full property declaration; for instance, if you want to include a call to NotifyPropertyChanged in your property's setter or if you want a read-only property in Visual Basic. However, just because you need a full property, you don't have to type all the required code in.

In C#, just type in the definition for the property's backing field. A property called LastName might have this as its backing field:

string lastName;

To create the property from the field, just right-mouse click on the declaration and, from the Refactor menu, select Encapsulate Field. Visual Studio will pop up a dialog box that will let you name the property and set some options on it (and you may not even have to do that much -- for my example, the dialog will default the property name to LastName, with an initial uppercase letter).

In Visual Basic, just type "pro" and press the Tab key twice (once to complete the keyword "Property" and the second time to trigger inserting the Property code snippet). Visual Studio will write your property with a backing field, a setter, and a getter. Type in your backing field's name and, when you press the Tab key again, you'll be moved to the backing field's data type. After setting the data type, press the Tab key one last time to move to the Property name and enter it. Everything else is taken care of for you.

Not all code snippets are as obvious as the property snippet. If you want Visual Studio to write the skeletons of your constructors, for instance, type ct and press the Tab key twice. Visual Studio will write a default constructor in your project's language and then position your cursor inside the constructor. Since I keep switching between C# and Visual Basic, I find this snippet especially useful: I don't have to pay attention to the differences in the languages.

Posted by Peter Vogel on 06/11/2013 at 1:16 PM0 comments


A Best Practice for Authenticating Users in ASP.NET MVC 4

If your site has even one or two actions where access is restricted to particular users, the smart thing to do is to restrict access to all the actions on your site and then selectively permit access to those actions that all users are allowed to request. That way, an error of omission (forgetting to make a method available) simply prevents users from accessing some action.

Unfortunately, by default ASP.NET MVC works exactly the opposite way: all actions are accessible to all users unless you specifically restrict access by applying the Authorization action filter to the method. Under this scenario, an error of omission (forgetting to put an Authorize attribute on a method) allows all users access to the action. It's literally the worst thing that can happen in a secure environment: unauthenticated and unauthorized access to a resource that should have been secured.

Global Filters provided a solution to this by allowing you to apply the Authorize attribute to all of your action methods, locking non-authenticated users out of your actions by default. You can then selectively override that setting by applying the Authorize attribute to individual methods, specifying specific roles and users authorized to use that action. That works, unless you have some action methods that don't require authentication, methods intended to be accessible to the general public. In that scenario, you can't use Global Filters to secure all of your action methods -- until ASP.NET MVC 4.

Implementing the best practice is possible in ASP.NET MVC 4 with the new AllowAnonymous action filter. The first step is to use the Global Filters in the FilterConfig class in the App_Start folder to apply the Authorize attribute to every action method:

public class FilterConfig
{
  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  {
    filters.Add(new AuthorizeAttribute);
  }
}

The next step is to selectively allow access to actions that don't require authentication by decorating them with the AllowAnonymous attribute:

[AllowAnonymous]
Public ActionResult Get()
{

Posted by Peter Vogel on 06/05/2013 at 9:03 AM0 comments


A For ... Each Extension for LINQ

A lot of the time, when I write a LINQ statement, I follow it with a For ... Each loop that processes each item in the query:

Dim db As New NorthwindModel
Dim ords = From o In db.Orders
           Where o.OrderDate > Date.Now
           Select o

For Each Ord As Order In ords
  '…do something with each selected order
Next

It made sense to me to create an extension method that would (a) attach itself to any LINQ query, and (b) run that For ... Each loop on each item returned from the LINQ query, like this:

Dim db As New NorthwindModel
Dim ords = (From o In db.Orders
            Where o.OrderDate > Date.Now
            Select o).ForEach(Sub (o)
				'…do something with each selected order)

This extension method accepts a lambda expression with the code to execute for each item. I also want my extension method to work with any type of object that comes out of a collection (extension methods automatically deduce the datatype of any collection they're used on). The declaration for my method begins like this:

Public Module PHVExtensions
    <Extension()>
    Public Sub ForEach(Of T)…

The first parameter passed to my method has to be the datatype of the class that I want my method to attach itself to -- in this case, anything that implements the IEnumerable interface. That IEnumerable class (some collection) will be automatically passed to my extension method through this parameter. Extending my declaration to support that gives this code:

Public Module PHVExtensions
    <Extension()>
    Public Sub ForEach(Of T)(coll As IEnumerable(Of T),…

The second parameter passed to my method will be the lambda expression that accepts a single parameter (an item from the collection). Since I'm using a lambda expression that doesn't return a value, I declare that parameter as an Action with its single parameter typed using my placeholder T. Here's the full code for declaring my extension method:

Public Module PHVExtensions
    <Extension()>
    Public Sub ForEach(Of T)(coll As IEnumerable(Of T), 
                               todo As Action(Of T))

    End Sub

End Module

Within my extension method, I simply loop through the collection passed in the first parameter and call the Action passed in the second parameter. As I call the Action, I pass in each item from the collection. The code inside my extension looks like this:

For Each itm As T In coll
  todo(itm)
Next
After doing all this work, I discovered that Igor Ostrovsky had already written this method along with a whole bunch of other useful LINQ extension methods, all in C#. You should check them out. I wish I had before I spent the time writing this code.

Posted by Peter Vogel on 05/31/2013 at 9:03 AM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.