Many developers use the ConfigurationManager class to retrieve settings from the .Config file of your application. This class allows you to retrieve settings from the <appSettings> element. With just a single line of code as shown in the following line:
file = ConfigurationManager.AppSettings["CustomerFile"];
The above code assumes you have the following setting declared in your App.Config or Web.Config file for your application:
<configuration>
<appSettings>
<add key="CustomerFile"
value="D:\Samples\Customers.xml" />
</appSettings>
</configuration>
This works great except in the case where you misspell the key name in your line of code, or you forget to add the element in the <appSettings> element in your .Config file. In either case, the value you get back will be a null value. Sometimes these null values can wreak havoc on your code because you forgot to check the value for null and the attempt to perform some operation on that value such as opening the file name. For example, the following code would cause a ArgumentNullException to be raised because the key value is misspelled.
string value = string.Empty;
value = ConfigurationManager.AppSettings["CustomerFil"];
System.IO.File.OpenText(value);
To fix the above code you need to test the “value” variable to see it is null prior to attempting to open the file as shown in the following code:
string value = string.Empty;
value = ConfigurationManager.AppSettings["TheValue"];
if (value == null)
MessageBox.Show("Can't open the file");
else
System.IO.File.OpenText(value);
MessageBox.Show(value.ToString());
Another issue with the above code is if you wish to change the location of where you are storing your application settings, you have to modify every line of code throughout your whole application where you used ConfigurationManager.AppSettings. For example, sometime in the future you might want to store your settings in an XML file located on a central server, or maybe store them in a database. This would be a lot of extra work due to you probably have a lot of places where you are retrieving configuration settings. Instead let’s wrap up the calls to the ConfigurationManager.AppSettings method in your own class.
Wrap Up Configuration Manager
A best practice that I have employed for over twenty years has been to wrap up any method calls that could potentially change in the future. Configuration settings, database access calls, registry settings, WCF Services, and similar types of classes are all candidates for wrapping up. Creating your own class allows you to change the methods for getting data from another source without you having to change the code in your application.
For the configuration settings shown previously, creating a class to wrap up the call to ConfigurationManager.AppSettings is a very simple task. Below is the complete class that will allow you to get a string and an integer value from a configuration file.
public class AppConfig
{
public string XmlPath { get; set; }
public int DefaultType { get; set; }
// Wrapper around ConfigurationManager.AppSettings call
protected string GetSetting(string key)
{
return ConfigurationManager.AppSettings[key];
}
public string GetSetting(string key, string defaultValue)
{
string value;
value = GetSetting(key);
if (value == null)
value = defaultValue;
return value;
}
public int GetSetting(string key, int defaultValue)
{
int ret;
string value;
value = GetSetting(key);
if (value == null)
ret = defaultValue;
else
ret = Convert.ToInt32(value);
return ret;
}
}
Notice how each of the public GetSetting methods call a protected method named GetSetting where the call to ConfigurationManager.AppSettings is made. Now, if you want to store your configuration settings in a database table, you only need to change the protected GetSetting method. All of the rest of the methods in this class and the calls you make in your application to the GetSetting methods in this class do not need to change at all.
In addition to wrapping up the call to the ConfigurationManager.AppSettings method call, you can add on additional functionality as well. For instance you can allow the programmer to pass in a default value to return if the value is not found in your settings storage location.
You call the GetSetting methods in AppConfig class using the following code:
AppConfig config = new AppConfig();
config.XmlPath = config.GetSetting("XmlPath", @"C:\");
MessageBox.Show(config.XmlPath);
In the above code if the “XmlPath” key was not found, then C:\ would be returned. The same call can be used for the overloaded version of GetSetting that returns an integer value. You pass in an integer value that you wish to have returned if the key “DefaultType” is not found.
AppConfig config = new AppConfig();
config.DefaultType = config.GetSetting("DefaultType", 1);
MessageBox.Show(config.DefaultType.ToString());
Summary
Wrapping up calls to .NET classes and their methods can give you more flexibility in the future if you wish to change the implementation of a method. In addition it allows you to add on functionality that is not present in the original calls. Wrapping up methods like this also protects you from changes that Microsoft might introduce in future versions of the .NET Framework. If they obsolete a class or method, you now only need to change your code in just place. The rest of your application does not need to change. In other words, you are helping to future-proof your code.
NOTE: You can download this article and the sample code that goes with this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Wrapping up Configuration Manager” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
Just wanted to let everyone know that I published a new video this morning on "Architecting Applications for Multiple UIs". This $20 video is an hour long and includes 3 sample applications in WPF, ASP.NET and Windows Phone with a common set of class libraries and WCF Services. This video walks you through how to create a View Model to talk to WCF Services and this same View Model is then used from all three of these UIs. Doing this saves you from writing a ton of front-end code. In fact the code behind in most of these is less than 50 lines of code! If you are interested take a look here: http://www.pdsa.com/Products/ProductDetail.aspx?prod=423
Thanks,
Paul
As programmer’s we know that if we create a temporary file during the running of our application we need to make sure it is removed when the application or process is complete. We do this, but why can’t Microsoft do it? Visual Studio leaves tons of temporary files all over your hard drive. This is why, over time, your computer loses hard disk space. This blog post will show you some of the most common places where these files are left and which ones you can safely delete.
.NET Left Overs
Visual Studio is a great development environment for creating applications quickly. However, it will leave a lot of miscellaneous files all over your hard drive. There are a few locations on your hard drive that you should be checking to see if there are left-over folders or files that you can delete. I have attempted to gather as much data as I can about the various versions of .NET and operating systems. Of course, your mileage may vary on the folders and files I list here. In fact, this problem is so prevalent that PDSA has created a Computer Cleaner specifically for the Visual Studio developer. Instructions for downloading our PDSA Developer Utilities (of which Computer Cleaner is one) are at the end of this blog entry.
Each version of Visual Studio will create “temporary” files in different folders. The problem is that the files created are not always “temporary”. Most of the time these files do not get cleaned up like they should. Let’s look at some of the folders that you should periodically review and delete files within these folders.
Temporary ASP.NET Files
As you create and run ASP.NET applications from Visual Studio temporary files are placed into the <sysdrive>:\Windows\Microsoft.NET\Framework[64]\<vernum>\Temporary ASP.NET Files folder. The folders and files under this folder can be removed with no harm to your development computer. Do not remove the "Temporary ASP.NET Files" folder itself, just the folders underneath this folder. If you use IIS for ASP.NET development, you may need to run the iisreset.exe utility from the command prompt prior to deleting any files/folder under this folder. IIS will sometimes keep files in use in this folder and iisreset will release the locks so the files/folders can be deleted.
Website Cache
This folder is similar to the ASP.NET Temporary Files folder in that it contains files from ASP.NET applications run from Visual Studio. This folder is located in each users local settings folder. The location will be a little different on each operating system. For example on Windows Vista/Windows 7, the folder is located at <sysdrive>:\Users\<UserName>\AppData\Local\Microsoft\WebsiteCache. If you are running Windows XP this folder is located at <sysdrive>:\ Documents and Settings\<UserName>\Local Settings\Application Data\Microsoft\WebsiteCache. Check these locations periodically and delete all files and folders under this directory.
Visual Studio Backup
This backup folder is used by Visual Studio to store temporary files while you develop in Visual Studio. This folder never gets cleaned out, so you should periodically delete all files and folders under this directory. On Windows XP, this folder is located at <sysdrive>:\Documents and Settings\<UserName>\My Documents\Visual Studio 200[5|8]\Backup Files. On Windows Vista/Windows 7 this folder is located at <sysdrive>:\Users\<UserName>\Documents\Visual Studio 200[5|8]\.
Assembly Cache
No, this is not the global assembly cache (GAC). It appears that this cache is only created when doing WPF or Silverlight development with Visual Studio 2008 or Visual Studio 2010. This folder is located in <sysdrive>:\ Users\<UserName>\AppData\Local\assembly\dl3 on Windows Vista/Windows 7. On Windows XP this folder is located at <sysdrive>:\ Documents and Settings\<UserName>\Local Settings\Application Data\assembly. If you have not done any WPF or Silverlight development, you may not find this particular folder on your machine.
Project Assemblies
This is yet another folder where Visual Studio stores temporary files. You will find a folder for each project you have opened and worked on. This folder is located at <sysdrive>:\Documents and Settings\<UserName>Local Settings\Application Data\Microsoft\Visual Studio\[8|9].0\ProjectAssemblies on Windows XP. On Microsoft Vista/Windows 7 you will find this folder at <sysdrive>:\Users\<UserName>\AppData\Local\Microsoft\Visual Studio\[8|9].0\ProjectAssemblies.
Remember not all of these folders will appear on your particular machine. Which ones do show up will depend on what version of Visual Studio you are using, whether or not you are doing desktop or web development, and the operating system you are using.
Summary
Taking the time to periodically clean up after Visual Studio will aid in keeping your computer running quickly and increase the space on your hard drive. Another place to make sure you are cleaning up is your TEMP folder. Check your OS settings for the location of your particular TEMP folder and be sure to delete any files in here that are not in use. I routinely clean up the files and folders described in this blog post and I find that I actually eliminate errors in Visual Studio and I increase my hard disk space.
NEW! PDSA has just published a “pre-release” of our PDSA Developer Utilities at http://www.pdsa.com/DeveloperUtilities that contains a Computer Cleaner utility which will clean up the above-mentioned folders, as well as a lot of other miscellaneous folders that get Visual Studio build-up. You can download a free trial at http://www.pdsa.com/DeveloperUtilities. If you wish to purchase our utilities through the month of November, 2011 you can use the RSVP code: DUNOV11 to get them for only $39. This is $40 off the regular price.
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Developer Machine Clean Up” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
Calling all Speakers!
My name is Paul Sheriff and I am one of the conference
chairs for DevConnections in the Spring of 2012 which will be held at the MGM
Grand in Las Vegas. I am looking for some great speakers in 3 different areas
of expertise.
1. Fundamentals Track
I need speakers that are adept at teaching business
application programmers how to move to .NET, XAML, HTML5, JavaScript and
JQuery. I am not looking for a re-hash of old seminar topics. I want new
"step-by-step" oriented seminars that show people how to do one or
two things well in VS.NET 2010 or later. I would really like step-by-step
seminars as much as possible. I am especially interested in those seminars that
show people how to move from old style programming to new style programming (Synchronous
to Asynchronous, WCF Services, SOA, XAML, HTML5, etc.) I am looking for those
seminars that teach the basics to business programmers across a wide variety of
topics. Below are the technologies/areas that I think would be good for this
track.
- Basics of HTML5
- Basics of JavaScript
- Basics of JQuery
- Moving from Synchronous programming to Asynchronous
- The Basics of C++ for Windows 8
- Suggest a topic…
2. Professional Development Track
This track will focus on the programmer who is moving up to
architect, project manager or a development manager. The intent is to present a
series of seminars that will help them build their skills in these areas.
- Project Management
- Requirements Gathering
- Estimating
- Architecture
- Suggest a topic…
3. Agile Track
This track will focus on how to implement the Agile process.
The attendee should be presented with sessions around implementing Agile,
Scrum, etc.
- Intro to Agile/Scrum
- Managing Agile/Scrum Teams
- Top 10 pitfalls of the Agile/Scrum process
- Suggest a topic…
*** NOTE: NEW SESSIONS NEEDED!!! ***
IMPORTANT: We want fresh sessions! If you have presented a
topic at DevConnections more than 2 times before, please do not submit those as
we will not accept them. We will really be interested in topics around Windows
8, Metro, HTML5 and JavaScript and JQuery.
If you are interested, please let me know by emailing me
directly at PSheriff@pdsa.com. Here is
what I need from you ASAP!
1. A title and short description of your proposed topic
2. Your willingness to present on a minimum of 3 topics
3. You are able to come March 26-March 29, 2012 to Las Vegas
to speak on your topics
5. DEADLINE! I need all of this by October 31, 2011
Please ALSO enter your abstract at http://www.deeptraining.com/devconnections/abstracts
Abstract Format
Please really think about your Title and Abstract. I would
prefer you to have it in the following format.
Title: The title should be very action oriented and
explain exactly what you will get from this session. Think “Marketing and
Sales”! You are selling your session to the attendees. Using numbers in your
title are a great way to gather interest, for example; “Top 10 tips for ____”,
“The 20 things you need to know to _____”, “You can learn _____ in just 75
minutes”, etc.
Description: Use a lot of action sentences and
explain each demo and each point that the attendee will get from attending this
seminar. Really sell this seminar to the attendee in here. If possible we would
like to have the user walk away with a class, a DLL, a reusable widget, flash
cards, a document with step-by-step instructions, or a set of concrete
techniques from this session. Give some value to the attendee. Make this “Take
Away” the last sentence in your abstract.
Please keep the abstracts under 200 words each and in one
paragraph. No bulleted items and line breaks, and please use a spell-checker.
You need to use the web-based tool to submit them officially, but send to me
too please. Please submit at least 3 abstracts, but it would help your chances
of being selected if you submitted 5 or more abstracts. Also, you are encouraged
to suggest all-day pre or post conference workshops as well. We need to
finalize the conference content and the tracks layout in just a few weeks, so
we need your abstracts no later than October 31, 2011. NO EXECPTION will be
granted on late submissions!
What you will get if selected:
- $500 per regular conference talk.
- Compensation for full-day workshops ranges from $500 for
1-20 attendees to $2500 for 200+ attendees.
- Airfare allowance of up to $500. If you are international,
you will have to cover the rest.
- Hotel stay paid by the conference.
- Free admission to the conference.
- Speaker party.
- Lots of fun!
Thanks,
Paul D. Sheriff
President
PDSA, Inc.
Microsoft Regional Director,
Southern California
www.pdsa.com
| (714) 734-9792, ext. 224
---------------------------------------------------------
PDSA, Inc. is a Microsoft
Partner in Southern California.
We specialize in Architecture
Planning & Assessment, Custom Software Development, .NET and SQL Server.
---------------------------------------------------------
As technology keeps moving on, we as developers are continually challenged to learn new ways of doing our jobs. Many years ago (starting as far back as Visual Basic 4.0) the movement was toward OOP and creating N-Tier applications. This meant wrapping up the data returned from DAO, RDO or ADO into classes and collections of classes. .NET came along and we started using ADO.NET to retrieve data. However, usage of classes and collection classes changed very little, at least conceptually. In .NET 2.0 Generics were introduced, but this just helped simplify our code. Again, our basic class structure changed very little.
If you were a normal desktop developer (Windows Forms) or an ASP.NET developer you were able to simply connect to your database, retrieve your data, and life was good. However, as more devices have exploded into our world, we are forced to learn new ways to consume our data. Most prevalent is the use of web services or Service Oriented Architecture (SOA). Luckily, web services can be consumed from desktop apps, web apps, and mobile apps. If you are doing desktop apps and web apps, you can most likely consume these services using a synchronous model. If you are using Silverlight, HTML5 with JS or other mobile applications, you will have to use an asynchronous model. Moving from synchronous to asynchronous is not too difficult; it just takes a little different style of programming.
The Product Class
In the sample code you will be using a Product class. This class has just four properties and is used to store a single product. This class is shown below:
public class Product
{
public int ProductId { get; set;}
public string ProductName { get; set; }
public DateTime IntroductionDate { get; set; }
public decimal Price { get; set; }
}
You can then create a collection of Product objects using a generic List<Product>. Of course you can use any method you want for creating a collection of Product objects.
Create a Collection of Products
The code to create a collection of Product objects has not fundamentally changed in years. In the code below I will use ADO.NET to just keep things simple. Feel free to use LINQ to SQL, the Entity Framework, or any other method you want. Just realize that under the hood, all of these technologies perform this same type of code.
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
public List<Product> GetProducts()
{
List<Product> ret = new List<Product>();
DataTable dt = new DataTable();
SqlDataAdapter da;
da = new SqlDataAdapter("SELECT * FROM Product",
ConfigurationManager.ConnectionStrings["Sandbox"].
ConnectionString);
da.Fill(dt);
foreach (DataRow item in dt.Rows)
{
Product prod = new Product();
prod.ProductId = Convert.ToInt32(item["ProductId"]);
prod.ProductName = Convert.ToString(item["ProductName"]);
prod.IntroductionDate =
Convert.ToDateTime(item["IntroductionDate"]);
prod.Price = Convert.ToDecimal(item["Price"]);
ret.Add(prod);
}
return ret;
}
In the code above you create a SqlDataAdapter object which is used to fill up a DataTable. You iterate over the rows in the DataTable and create an instance of a Project class. You fill each property of the Product object with the corresponding data from the column you retrieved from the Product table. This new Product object is added to the collection class. Again, this type of code has not changed in over 15 years. You would have written very similar code in Visual Basic, as far back as version4.0.
Accessing Data Directly (The Old Way)
From a Windows Forms, WPF or ASP.NET application you can use the above code directly from your front end to load data into a list box or other list-type control. In the sample code you can download with this article, there is a user control with a Load Products (Local) button (Figure 1).

Figure 1: Samples to load Product Data
When you click on this button you run the following code:
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
List<Product> coll;
try
{
coll = GetProducts();
lstData.DataContext = coll;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
In this click event you simply call the GetProducts() method directly in a synchronous manner. While this is fine for a normal desktop application, if you wish to use this code in Silverlight, Windows Phone, Windows 8 Metro, or any of the other mobile devices you will need to use a service. To start this process, let’s take a look at how to create a service using WCF and then call this service synchronously. Later in this article you will then call this same WCF service asynchronously.
Accessing Data Synchronously From a Web Service
Creating a service application is very easy in Visual Studio. You simply choose New Project and select WCF from the list of installed templates. Choose the WCF Service application from the list of template projects. Give this new service project a name of ProductService. Next, delete the IService.cs and Service.svc files. It is easier to delete and just add a new name than to rename the files and classes. Now add a new WCF Service called ProductService. This creates two new files in your project; IProductService.cs and ProductService.svc. Into the IProductService interface you will define a contract that specifies a method name and the return value from that method.
[ServiceContract]
public interface IProductService
{
[OperationContract]
List<Product> GetProducts();
}
In the code behind of the ProductService.svc you will then drop in the GetProducts() method you wrote before. You will need to add a <connectionStrings> element in the Web.config file that the service can use to connect to the database where your product data resides.
Back in your client code, you now need to add a Service Reference to your WCF service. Name this service ProductSyncServiceReference. In the sample for this article, which is named SyncToASync, you will then need a using statement to use the classes in the namespace created by the Service Reference dialog.
using SyncToASync.ProductSyncServiceReference;
Next, you write code under the Load button’s click event procedure to call the GetProducts method in this WCF service. The generated code creates a class called ProductServiceClient that knows how to connect to your service endpoint. You will create an instance of this class and call the GetProducts method as shown in the code below.
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
List<Product> ret;
ProductServiceClient productService =
new ProductServiceClient();
try
{
ret = productService.GetProducts();
productService.Close();
lstData.DataContext = ret;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This code calls the WCF service, the service gathers the data, and then the collection of Product objects is returned from the service. All of this happens synchronously, which means that until the service calls finishes your code and UI are frozen on this one line of code.
Let’s now look at how to make this call asynchronously and thus free up your UI and other code to run while the code to fetch the data waits for the data from the service.
Accessing Data Asynchronously From a Service
You can call this same WCF Service asynchronously from your WFP, Windows Forms or ASP.NET application (as well as Silverlight and Windows Phone). When you create the service reference in your WPF application you will need to click on the Advanced… button (Figure 2) to specify that you wish to generate asynchronous method calls (Figure 3). You do not need to do this step with Silverlight and Windows Phone as this dialog knows that the only option is asynchronous in these environments.
It is a good idea to also choose System.Collections.Generic.List in the Advanced dialog. What this option does is to map any List<T> objects that you return from your WCF service are returned as a generic collection. By default, WCF services will return an array because that is more usable by other consumers other than .NET. Since we are using .NET, we can take advantage of Generics.

Figure 2: Click the Advanced Button to create asynchronous code

Figure 3: Change the async and collection types
Now in your client side code, you will again need to add a using statement to bring in the namespace for the asynchronous web service reference.
using SyncToASync.ProductAsyncServiceReference;
Now you write your code in the Click event for your button. This code will be different from the synchronous version of this code. First you need to create an instance of the ProductServiceClient outside of any event procedures in your window as shown below:
ProductServiceClient _ProductService =
new ProductServiceClient();
You need the variable that points to the ProductServiceClient to be defined as a field in your C# class because you need to call a method on this object in one method, but you will need to close the connection through this object in another method. Thus, you need to define this variable at the class level so all methods and events in this class can use this variable.
When you clicked on the “Generate asynchronous operations” check box this causes the code generator to create a “Completed” event and a “GetProductsAsync()” procedure. You first hook up an event procedure to call back into after the data has been gathered asynchronously and returned back to the client. Next you call the GetProductsAsync method to start the asynchronous process of gathering the data in the background.
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
_ProductService.GetProductsCompleted += new
EventHandler<GetProductsCompletedEventArgs>
(client_GetProductsCompleted);
_ProductService.GetProductsAsync();
}
In the “Completed” event procedure you will get an event argument that contains a “Result” property. In this property is the return value from the call to your web service. In this case it is a generic List collection of Product objects. You can take that data and put it into the DataContext property of your list box. If you have bound your list box correctly, then the product data will be displayed after the call to the Completed event is finished. At this point you should also close the connection to the Product service.
void client_GetProductsCompleted(object sender,
GetProductsCompletedEventArgs e)
{
lstData.DataContext = e.Result;
_ProductService.Close();
}
Summary
Asynchronous programming will become more and more prevalent with Windows 8 as that will be the only supported model for most of the APIs and certainly for any Metro-style application. You can start learning and using Asynchronous programming today and prepare for the future. Start slowly by adding a few calls to a service from your existing applications. Have fun!
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Synchronous to Asynchronous Data” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
After my last blog post on how to layout a different UI design instead of a normal tabular format, I had quite a few comments on how you would add sorting, paging and filtering and so on. That is one of the best parts about using the GridView control, you can still use all the normal sorting, paging and filtering that you would with a normal tabular GridView. If you take a look at Figure 1 you can see that I sorted the data using the SqlDataSource object, then applied paging and added a Search/Filtering mechanism. I also added a drop down list of field names so you can sort the grid using any field from the table you want. All of this was done and you will only have to add 1 line of code to perform the sorting!

To make this form work, here is what I had to do.
I added a Label, TextBox and Button at the top of the page. I also added a DropDownList control and hard coded the collection of items with “CompanyName”, “LastName”, and “EmailAddress”.
The TextBox I named txtCompany and set its AutoPostBack property to true. The button is really just a placeholder and has no code behind it whatsoever. This allows me to tab off the TextBox which will cause a post back to occur, which in turn will force the SqlDataSource object that controls the grid to re-bind and apply the filter from the value typed into the TextBox.
To the GridView control, I added the following attributes:
- AllowPaging="True"
- PageSize="2"
- AllowSorting="True"
To the SqlDataSource I then added modified the SelectCommand to add an ORDER BY on CompanyName to sort the data. I then added a FilterExpression with the expression “CompanyName LIKE ‘{0}’’. The {0} placeholder will be filled in with whatever value you type into the txtCompany text box.
Next I created a FilterParameters element within the SqlDataSource and created a ControlParameter element which specifies the name of the parameter, the control to use (txtCompany) and the property on the control that I wish to get the value for the parameter (Text).
<asp:SqlDataSource ID="custData"
runat="server"
ConnectionString="<%$
ConnectionStrings:AdvWorksConnectionString %>"
SelectCommand="SELECT * FROM SalesLT.Customer
ORDER BY CompanyName "
FilterExpression="CompanyName LIKE '{0}%'">
<FilterParameters>
<asp:ControlParameter Name="CompanyName"
ControlID="txtCompany"
PropertyName="Text" />
</FilterParameters>
</asp:SqlDataSource>
That is all there is to it! No code behind, just using normal GridView and SqlDataSource parameters.
Styling the Buttons
Another enhancement I added to this ASP.NET page is I styled the buttons a little so we did not have the default button look. This was easy to do by just adding a .CSS file and added the following class.
input.submit {
color:#050;
font: bold 84% 'trebuchet ms',helvetica,sans-serif;
background-color:#fed;
border:1px solid;
border-color: #696 #363 #363 #696;
}
I added a <link> reference to the aspx page that referenced this style and set the CssClass=”submit” to each button control on the page.
Sorting the GridView
To sort the GridView control, you first set the AutoPostBack property to True on the DropDownList so when you change the value, a post back will occur and the SelectedIndexChanged event will fire. In this event you can then pass the selected value from the drop down list to the Sort method on the GridView.
protected void sortFields_SelectedIndexChanged(object sender,
EventArgs e)
{
grdCust.Sort(sortFields.SelectedValue.ToString(),
SortDirection.Ascending);
}
Summary
In this blog you learned how to add paging, sorting and filtering to your grid view control. You also learned to apply a little styling to your buttons. I hope these two blog posts will help you to think about alternate UI designs other than the typical tabular format. I know your users will thank you. We have found that our users find user interfaces that are not so busy and show important data in a larger font size easier to use. Have fun!
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “An Alternate Approach to a GridView-Part 2” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
I have long had a problem with using grids to display data to the user. I have an even bigger problem with editing on a grid. A grid is easy to implement for a developer, and this is normally why developers use them. However, a grid is normally not the best interface for a user. Now, note that there are always exceptions, but these should be the exception and not the rule. There are many reasons why a grid is not suitable for user consumption.
A grid presents too much data on the screen so the user’s eye has too much to try to concentrate on
A user will get much more tired at the end of the day using a grid as opposed to other display types
The user cannot distinguish between the data in each column since each column is very uniform and nothing stands out
The header for the data can scroll out of sight and thus the user can no longer distinguish what data is what in each column
The above is just some of the reasons why a grid should not be the appropriate choice for displaying a list of data to the user. Just take a look at Figure 1 and then take a look at Figure 2 and see which one you think is easier to read.

Figure 1: The normal GridView control

Figure 2: Using a Template will make your GridView easier to read for the user
Now, both of the above .aspx pages use a GridView control. However, the version of the GridView shown in Figure 2 uses a TemplateField to layout each row of data in the GridView. The version shown in Figure 1 uses just the normal column controls in a GridView.
Each of the above GridView controls use a SqlDataSource object to retrieve data from the SalesLT.Customer table in the AdventureWorksLT sample database. This SqlDataSource object is shown in the code below:
<asp:SqlDataSource
ID="custData"
runat="server"
ConnectionString="<%$
ConnectionStrings:AdvWorksConnectionString %>"
SelectCommand="SELECT * FROM SalesLT.Customer">
</asp:SqlDataSource>
The first GridView control uses a couple of ButtonField controls for the Edit and Delete hyperlinks shown in the first two columns, followed by BoundField controls to display each column of data. The first GridView source is shown in the code below but has all the formatting removed to keep the source simple.
<asp:GridView>
<Columns>
<asp:ButtonField CommandName="Edit" Text="Edit" />
<asp:ButtonField CommandName="Delete" Text="Delete" />
<asp:BoundField HeaderText="Company Name"
DataField="CompanyName" />
<asp:BoundField HeaderText="First Name"
DataField="FirstName" />
<asp:BoundField HeaderText="Last Name"
DataField="LastName" />
<asp:BoundField HeaderText="Email Address"
DataField="EmailAddress" />
<asp:BoundField HeaderText="Phone"
DataField="Phone" />
</Columns>
</asp:GridView>
The second version of this GridView uses a TemplateField control within a single column in the GridView. In this TemplateField you can define any HTML you want. With just a little creativity you can create a much better layout than Figure 1.
The reasons the second version of the grid is better than the first are 1) The most important piece of data, the Company Name, is in a larger font than the other data that is less important; 2) You keep the labels close to the data as opposed to in headers on the grid that will eventually scroll out of sight; 3) Having the data go top left to bottom right in terms of importance is how most people in the western culture tend to process data.
The HTML code to create this version of the GridView is shown below. Again, all of the formatting code has been removed to keep the source code simple.
<asp:GridView ShowHeader="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div style="border: 1px solid gray; margin: 12px">
<div style="font-size: x-large">
<%# DataBinder.Eval(Container.DataItem,
"CompanyName") %>
</div>
<div>
Contact:
<%# DataBinder.Eval(Container.DataItem,
"FirstName")%>
<%# DataBinder.Eval(Container.DataItem,
"LastName")%>
(<%# DataBinder.Eval(Container.DataItem,
"EmailAddress")%>)
</div>
<div>
Phone:
<%# DataBinder.Eval(Container.DataItem, "Phone")%>
</div>
<br />
<div>
<asp:Button ID="btnEdit" Text="Edit"
CommandArgument='<%#
DataBinder.Eval(Container.DataItem,
"CustomerID")%>'
CommandName="Edit" runat="server" />
<asp:Button ID="btnDelete" Text="Delete"
CommandArgument='<%#
DataBinder.Eval(Container.DataItem,
"CustomerID")%>'
CommandName="Delete" runat="server" />
</div>
</div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
As you can see, the second version will take a little more thought and a little more HTML code, but your users will thank you.
Summary
Next time you are designing how to display a lot of data to your users, really think about how you can make this display simpler. Normally all it takes is a little discussion with your user to find out what data is most important. That data should be made to stand out in your list. You can still use a GridView control, but take advantage of the TemplateField control and HTML to create a list that really works for your user. Remember, your user is the one that has to live with your application day in and day out. You want them thanking you at the end of the day, not cursing you!
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “An Alternate Approach to a GridView” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
Prior to .NET Version 2.0 if you wanted to hold a collection of string, integers, or objects you had to work with some of the classes in the System.Collections namespace.
This namespace contains classes and interfaces needed to define collections of objects. Some of the classes are listed in Table 1.
| Class |
Description |
| ArrayList
|
An ArrayList is similar to an array, but the ArrayList class allows you to add items without managing the size of the list yourself (much like a VB Collection object). |
| CollectionBase
|
This class is the base for a strongly-typed collection, critical for creating collection classes, described below.
|
| DictionaryBase
|
This class is the base for a strongly-typed collection utilizing associated keys and values. This is similar to the Dictionary object found in VBScript and used by many ASP developers.
|
| SortedList
|
This class represents a collection of keys and values, and is automatically sorted by the key. You can still access the values with either the key or the index number.
|
Table 1. System.Collections classes
Assume you create a class called Customer. The Customer class has a number of properties, methods, and events. You then want to create several Customer objects within one structure so you can iterate through the collection, performing some operation on each object. You could just create a variable of type Array, ArrayList, or SortedList, but these standard collections can hold any type of object. In other words, you could add a Customer object as the first item in the collection, but you could then add an Employee object as the second item, a string as the third, and so on. If you try to iterate over this collection and apply the Update method, it might work on the Customer and Employee objects, but when your loop attempts to call the Update method of a String object, it will certainly fail.
To get around this sticky situation, you can create your own class that looks like a generic collection object, but restricts its members to only one data type. This new class will include the standard methods of the collection base type, such as the Add and Remove methods, as well as an Item property, but your class’ Add method will only allow you to add Customer objects.
The .NET Framework 2.0 introduced a new namespace called System.Collections.Generics which provides a series of classes that closely resemble the classes in System.Collections. However, these new classes automatically provide the ability to contain only one type of object.
System.Collections Example
Assume that you need to create a Customer object. The structure of the Customer object is very simple, containing just a CompanyName property. Imagine that you want to create a collection class named Customers (note the “s” on the end) to hold a set of Customer objects. You first need to create the Customer class as follows:
public class Customer
{
public string CustomerName;
}
Next you create your new Customers collection class. Your class must inherit from the System.Collections.CollectionBase class. This base class gives you all of the functionality of a normal collection, but allows you to override any of the base methods, such as Add and Item. The following code provides the new class, and its overridden Add and Item members:
public class Customers : System.Collections.CollectionBase
{
public void Add(Customer cust)
{
base.List.Add(cust);
}
public void Remove(int Index)
{
if(Index > Count - 1 || Index < 0) {
// Return error message
}
else
base.List.RemoveAt(Index);
}
// This is the "Item" indexer
public Customer this[ int index ]
{
get
{
if (index > Count - 1 || index < 0) {
// Did not find Customer
return null;
}
else
return (Customer) base.List[index];
}
}
}
In your collection class, you’ll need to override the Add method so that instead of accepting a generic Object type, your method accepts only a Customer object. You can then use the internal List property from the base class to add the customer object to the internal collection of generic objects.
You also need to override the Item method so it returns a Customer object instead of a generic Object data type. This function converts the data in the built-in List property from a generic Object data type to a Customer data type. In C# you need to use the indexer syntax to return an item from this collection. This is done using the syntax shown below:
// This is the "Item" indexer
public Customer this[ int index ]
{
get
{
if (index > Count - 1 || index < 0)
{
// Did not find Customer
return null;
}
else
return (Customer) base.List[index];
}
}
Using inheritance, you end up writing a lot less code to implement a collection class when compared to the code you had to write in older language that did not have inheritance. To use this class, you could write code like the following:
private void CustCollection()
{
Customer cust;
Customers custColl = new Customers();
StringBuilder sb = new StringBuilder();
cust = new Customer();
cust.CustomerName = "Microsoft Corporation";
custColl.Add(cust);
cust = new Customer();
cust.CustomerName = "PDSA, Inc.";
custColl.Add(cust);
sb.Append("Count = " + custColl.Count.ToString());
sb.Append(Environment.NewLine);
foreach(Customer c in custColl)
sb.Append(c.CustomerName + Environment.NewLine);
lblMsg.Content = sb.ToString();
custColl.RemoveAt(0);
lblMsg.Content += "After the removal = " + custColl.Count;
}
The above code creates two new Customer objects, sets the CustomerName property of each to a unique name and then adds each one to the Customers collection class. You can use the Count property from the base class to determine the number of items in the collection, even though you did not implement it in your Customers class. You can use the For Each iterator to loop through each customer object. You can also utilize the base class’ RemoveAt method to remove a specific item at a specified index in the collection.
System.Generics.List Example
Let's now take the same sample shown previously and see how this would work with Generics. The code is considerably simplified since the Generics List class handles all the normal add and remove operations. In addition, using the List<Customer> forces type-safety onto the collection. This means nothing but an object of the type Customers is allowed into this Generic List collection.
public class Customers2 : List<Customer>
{
}
You can now write the exact same code to manipulate this Customers2 class in the exact same way you use the Customers class.
private void CustomerCollection()
{
Customer cust;
Customers2 custColl = new Customers2();
StringBuilder sb = new StringBuilder();
cust = new Customer();
cust.CustomerName = "Microsoft Corporation";
custColl.Add(cust);
cust = new Customer();
cust.CustomerName = "PDSA, Inc.";
custColl.Add(cust);
sb.Append("Count = " + colcust.Count.ToString());
sb.Append(Environment.NewLine);
foreach(Customer c in custColl)
sb.Append(c.CustomerName + Environment.NewLine);
lblMsg.Text = sb.ToString();
custColl.RemoveAt(0);
lblMsg.Text += "After the removal = " + custColl.Count;
}
As you can see the code from a usage perspective is exactly the same, however, the Customers2 class has eliminated all of the code from the Customers class because of the use of the Generics List<T> class.
Summary
There really is no reason to use the CollectionBase class anymore. In fact, you can not use CollectionBase in Silverlight or Windows Phone apps. You may still find reasons to use ArrayList and possibly even SortedList or other non-generic collections, however, 99% of the time you will take advantage of the Generics namespace and classes.
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Generic Collections” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
When you first start designing XAML screens in either WPF or Silverlight there are several approaches you can take. You can just draw controls on a Grid and let the controls figure out where they are in relation to one another and the Window via the Margin property. You can also a Grid and create a set of Row and Column definitions similar to an HTML table. Another method is to use absolute positioning with a Canvas control. Finally, you could use a series of StackPanel controls with styles. Which one you choose has ramifications to how well your application looks and feels across a wide variety of resolution sizes. This article will explore the impact of each of these.
Setup Global Styles
In order to have a consistent look and feel across many windows in your application it is a good idea to open your App.xaml/Application.xaml file and add some application resources. In this sample you will use buttons, text boxes and text blocks, so create the following resources.
<Application.Resources>
<Style TargetType="Button">
<Setter Property="Margin"
Value="4" />
</Style>
<Style TargetType="TextBox">
<Setter Property="MinWidth"
Value="200" />
<Setter Property="Margin"
Value="4" />
<Setter Property="HorizontalAlignment"
Value="Stretch" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin"
Value="4" />
</Style>
</Application.Resources>
The above resources tell WPF/Silverlight that when rendering a Button set the Margin property to 4. When rendering a TextBox control to set the MinWidth property to 200, set the Margin to 4 and set HorizontalAlignment to Stretch. When rendering a TextBlock set the Margin property to 4.
Using Grid and Margin
If you create a new WPF/Silverlight Project and just start dragging and dropping controls onto the design surface. Each of the controls is put into the <Grid> and the margin of each control is set to a specific value that controls how far away the top and left of the control is from the <Grid>. Each control also sets a default height and width and sometimes a horizontal and vertical alignment property. All of these properties can render a form that looks like Figure 1 at design time.

Figure 1: Drag controls into the Grid without rows and columns
However, when you run the particular control it could look different based on your monitor. On my monitor Figure 2 is what was rendered. The arrows point out where things are chopped off due to the resolution of my monitor.

Figure 2: Controls can render differently at runtime
Let’s look at the XAML that rendered this particular form.
<Grid>
<TextBlock Height="28"
Margin="12,18,0,0"
Name="label1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="120"
Text="First Name" />
<TextBox Height="24"
Margin="0,18,61,0"
Name="textBox1"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="192" />
<TextBlock Height="28"
HorizontalAlignment="Left"
Margin="12,52,0,0"
Name="label2"
VerticalAlignment="Top"
Width="120"
Text="Last Name" />
<TextBox Height="24"
Margin="125,52,61,0"
Name="textBox2"
VerticalAlignment="Top" />
<Button Height="23"
Margin="125,86,191,0"
Name="button1"
VerticalAlignment="Top"
Content="Close" />
</Grid>
If you were to draw this form, your actual values would vary slightly, but would be similar to the above. The problem with this XAML is you have hard-coded height and width properties and hard-coded margins. If the user tries to resize this form, changes the font size in their OS, changes their screen resolution, then this form will most likely not render correctly. Some of the text could get chopped or clipped depending on what changed. This is not acceptable. Thus, just dragging and dropping controls onto a XAML form is NOT the way to design screens.
Using a Canvas Control
Another method of doing absolute positioning similar to what you did above is to use a Canvas control. The canvas control does not use the Margin property to position your controls however. Instead it will use an attached property to each control to specify the Top and Left coordinates on the Canvas to draw that particular control. The good thing about the Canvas is it will not generate all of the XAML you saw in the previous example and will still generate a form that looks similar as shown in Figure 3:

Figure 3: A Canvas control gives you precise top and left coordinates for each control
The XAML is much cleaner as shown below:
<Canvas>
<TextBlock Canvas.Left="5"
Canvas.Top="10"
Text="First Name" />
<TextBox Canvas.Left="110"
Canvas.Top="10"
Name="txtFirst" />
<TextBlock Canvas.Left="5"
Canvas.Top="50"
Text="Last Name" />
<TextBox Canvas.Left="110"
Canvas.Top="50"
Name="txtLast" />
<Button Canvas.Left="110"
Canvas.Top="90"
Name="btnClose"
Content="Close" />
</Canvas>
While this XAML is much cleaner, we still have the problem that the controls will not resize if the form resizes. However since there are no hard-coded width or height properties if you change the FontSize property the control will grow or shrink. The bad part is that if it grows too much it will overlap any of the other controls since they are hard coded to start at a specific coordinate as shown in Figure 4:

Figure 4: Changing the FontSize can cause controls to render behind other controls
This behavior can serve to your advantage however if you want controls to overlap. In fact, the Canvas does add a ZIndex property that you can set on controls to determine which control is in front or in back of other controls.
Using Stack Panels
Another method of creating the same form you have seen is to use one StackPanel to get other StackPanels to stack vertically. Each pair of TextBlock and TextBox combination you want to place into the outer stack panel is placed inside of another StackPanel control with the Orientation property set to Horizontal. Figure 5 shows the same screen rendered using stack panel controls.

Figure 5: Stack Panels with the use of styles can render flexible forms. However, they cannot be resized.
In this WPF Window, you first add a Keyed resource to control the size of the TextBlock controls on this particular screen. This will ensure that each text block will take up the same size.
<Window.Resources>
<Style TargetType="TextBlock"
x:Key="LabelStyle">
<Setter Property="Width"
Value="100" />
<Setter Property="Margin"
Value="4" />
</Style>
</Window.Resources>
Below is the XAML for this screen.
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource LabelStyle}"
Text="First Name" />
<TextBox Name="txtFirst" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource LabelStyle}"
Text="Last Name" />
<TextBox Name="txtLast" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource LabelStyle}" />
<Button Name="btnClose"
Content="Close" />
</StackPanel>
</StackPanel>
Notice the use of the Style property on the TextBlock controls to ensure that the width of each TextBlock is set to the same value. This works for most scenarios, but if you try to change the FontSize you will again get clipping of your controls as shown in Figure 6.

Figure 6: Changes to FontSize will still clip.
So using a StackPanel control is also not an ideal situation for an overall page layout. StackPanels are very useful as a portion of a page however.
Using Grid with Rows and Columns
For creating business application forms that are resizable and respond well to changes in font size and screen resolution changes, the best approach is to use a Grid with Row and Column definitions. This is very similar to using a Table in HTML, however, the syntax is very different than HTML. Figure 7 shows the same screen created using rows and columns in a Grid.

Figure 7: Use a Grid with Row and Column Definitions for the most flexibility.
The XAML to create this screen is shown below:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
Name="label1"
Text="First Name" />
<TextBox Grid.Column="1"
Grid.Row="0"
Name="textBox1" />
<TextBlock Grid.Column="0"
Grid.Row="1"
Name="label2"
Text="Last Name" />
<TextBox Grid.Column="1"
Grid.Row="1"
Name="txtLast" />
<Button Grid.Column="1"
Grid.Row="2"
Name="button1"
Content="Close" />
</Grid>
Within a Grid control you create a set of RowDefinition and ColumnDefinition constructs to specify how many rows and columns. You also specify on each row and column the Width and Height. To be truly resizable you want to make sure you never hard code a number into either of these properties. You always want to use “Auto” or “*”, or maybe “1*” or “2*”. Using Auto specifies that the row or column will size all rows or columns according to the largest child control within that row or column. An asterisk means to use all available remaining space. Typically the asterisk is used when you have a List control such as a ListBox, ListView or DataGrid within a row.
If you run this screen you can change font sizes, change screen resolution and resize the screen and all the controls will grow and shrink appropriately. Of course, you can always shrink the screen to a size that is too small for any of the controls. You can control this with the MinWidth and MinHeight properties on the Window or User Control where these controls are hosted.
Summary
Knowing the different methods to layout a screen in XAML is very important. Choosing the correct layout method will ensure that you have an application that is flexible to respond to your users’ differing hardware and OS configuration settings. Of course your layout needs may vary based on your application needs. Where a Canvas won’t work on one screen, it may work very well on another. StackPanels and Grids can also be used together and in combination with ScrollViewers to ensure that even if the user shrinks the screen too much, at least they can still scroll to the rest of the controls.
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “XAML Layout” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
I recently had a client ask how to retrieve a list of Active Directory Domains as he wanted to give a list to his user. Turns out this is very easy to do in .NET. All you have to do is add a Reference to the System.DirectoryServices DLL and add a using statement:
using System.DirectoryServices.ActiveDirectory;
I typically like to create a class so I can gather information from each Domain object in the DomainCollection and have a set of properties that I can bind to in my applications. For example, in my customer’s application I needed to retrieve the LDAP path. Turns out you can get this path from the Domain object by calling the GetDirectoryEntry() method and retrieving a DirectoryEntry object. You can then get the LDAP path using the Path property. For this sample, I created a class called ADDomain. This class has two properties; Name and Path. Feel free to add additional properties if you need them.
public class ADDomain
{
public string Name { get; set; }
public string Path { get; set; }
}
Next you write a simple method to return a List of ADDomain objects. The method, called GetDomains() in this sample will first connect to a domain using the static method GetDomain on the Domain class. This method requires that you pass in the name of one of the domains in your network, and a user id and password that has access to this domain.
Once you have a valid Domain object you can now retrieve the Forest property from this Domain. With the Forest object you can now loop through all of the domains in the Domains collection that is part of the Forest object.
As you loop through each domain you get the information you are interested in and put that data into a new instance of a ADDomain object. This new object is added to your List<ADDomain> collection. Below is the complete method:
public List<ADDomain> GetDomains(string domainController,
string userName, string password)
{
Domain domain = null;
List<ADDomain> ret = new List<ADDomain>();
Forest forest = null;
try
{
// Connect to Domain
domain = Domain.GetDomain(
new DirectoryContext(
DirectoryContextType.Domain,
domainController,
userName,
password));
// Get Current Domain Forest
forest = domain.Forest;
// Get all Domains in Forest
foreach (Domain item in forest.Domains)
{
ADDomain ad = new ADDomain();
// Create new class to get the Path
ad.Name = item.Name;
ad.Path = item.GetDirectoryEntry().Path;
ret.Add(ad);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return ret;
}
After you have built the list of ADDomain objects, return that collection from this method. You can then use that collection to populate any list on any platform such as WPF, Silverlight or ASP.NET.
Summary
In this blog post you learned to get a list of Active Directory (AD) domains by using the classes and methods contained in the System.DirectoryServices.ActiveDirectory namespace. There are many classes contained in this namespace that can be used to do almost anything with AD. In a blog post earlier this year I showed how you can use this namespace along with WPF to create a login screen where users can authenticate against an AD domain. Explore this rich set of classes for your AD tasks.
NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Get List of Active Directory Domains” from the drop down list.
Good Luck with your Coding,
Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!
More Posts
Next page »