vanguard, noun - any creative group active in the innovation and application of new concepts and techniques in a given field (especially in the arts)
confusion, noun - a mental state characterized by a lack of clear and orderly thought and behavior; "a confusion of impressions"
clarifying where possible, things which need it.
2007-11-15
ASP.NET Gridview SelectIndexChanged event not firing
Well, dear reader, that's because you didn't set the Gridview.ID property, and when the callback for the event is fired, it does that by ID/parameters.. The parameters are there, but the ID isn't.. So it can't find your control, so it can't fire the event.
So, always assign the ID of dynamically generated ASP.NET controls!
2007-10-11
Changing Visual Studio Item Templates
For example -- Making a new class.
Now, I usually just right-click on my project list, Add..., New Item, then I'm presented with an array of the available Item Templates. So, I'll select Class, rename it, and then I'm presented with this:
using System;
using System.Collections.Generic;
using System.Text;
namespace MyNamespace
{
class Class1
{
}
}
And of course, the first thing I will do, is change the class name, set it to public, create an empty constructor, define code regions to keep things organized... and end up with something like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace MyNamespace
{
public class Class1
{
#region Constructors
public Class1()
{
Init();
}
///
/// Initializes field values.
///
private void Init()
{
}
#endregion Constructors
#region Fields
#endregion Fields
#region Properties
#endregion Properties
#region Public Methods
#endregion Public Methods
#region Private Methods
#endregion Private Methods
}
}
WHOA! That takes quite a few minutes of typing... FOR EVERY CLASS I WRITE!!
So, I decided to go figure out how those templates work.
Where are those files at?
The templates are stored in your Visual Studio installation directory. If you're like me, and running a fairly recent version of Visual Studio 2005, installed with default configuration, your install directory will probably be:
C:\Program Files\Microsoft Visual Studio 8\
and the templates are stored in:
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplates
Under that directory you'll find subdirectories for each classification of template (CSharp, JSharp, VisualBasic, etc.. ), and in each of those subdirectories, you'll find a zip file for each template.
For what I want to fix, I am looking for this file:
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplates\CSharp\1033\Class.zip
*sidenote: Notice that the last subdirectory in the path is the language code 1033 (English) and if you've installed windows/vs with a different language, this will be different.. this is one reason you may not see your default templates when working across languages (ie, windows is in spanish, and visual studio is installed from the English language version, but is configured to be in spanish.. templates will be missing!!
In the Class.zip file, you will find two files; Class.cs and Class.vstemplate
Class.vstemplate
Class.vstemplate is just an XML file. This contians information about the template, such as what GUID to lookup for the icon to display in the wizard screen, what the sorting order is, what assemblies it references, etc.. For the most part, unless your doing something more complicated than what I want to do, you won't need to edit this. One tag to pay attention to is:
<ProjectItem ReplaceParameters="true">Class.cs</ProjectItem<
This tag says that VS should make a new project item based on Class.cs, and it should parse the file and replace the parameter tokens in it with the appropriate values... So let's look at Class.cs:
Class.cs
Class.cs is the templated code file. The default file looks like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace $rootnamespace$
{
class $safeitemrootname$
{
}
}
So this is the normal new empty class, and the tokens $rootnamespace and $safeitemrootname$ are what will get replaced when VS parses the file and passes in the parameters.
Well, I don't know anything about those parameters... So I'm not going to mess with them. However, I did go make a list of the parameters I found in the default templates ( I could not find a list of these paramaters on the net anywhere...)
$rootnamespace$
$safeitemrootname$
$registeredorganization$
$year$
$guid1$
$ContentTags$
$MasterPage$
$fileinputname$
$classname$
$safeitemname$
So I modified Class.cs to be:
using System;
using System.Collections.Generic;
using System.Text;
namespace $rootnamespace$
{
public class $safeitemrootname$
{
#region Constructors
public $safeitemrootname$()
{
Init();
}
/// <summary>
/// Initializes field values.
/// </summary>
private void Init()
{
}
#endregion Constructors
#region Fields
#endregion Fields
#region Properties
#endregion Properties
#region Public Methods
#endregion Public Methods
#region Private Methods
#endregion Private Methods
}
}
Yay! my fingers are saved... but what you say? all my base are NOT belong to us? True. There is a cache.
Refreshing the Visual Studio Template Cache
The template files are cached in a folder called TemplateItemCache in the same location as the template folder. So..
- Close all Visual Studio Windows
- Clear contents of TemplateCache folder
- Open a DOS prompt (normal one, or Visual Studio 2005 Command Prompt)
- Run devenv /installvstemplates (if that doesn't work, run devenv /setup)
Now, when you restart Visual Studio, your new templates will be installed...
BUT! the fun doesn't stop here! The same templating structure for items also applies to projects! But that's next post...
2007-07-10
CodeSnippet: PrintObject
I write a number of small command-line utilities, and typically, I create a "property bag" type of object that contains all of the possible command-line options. Just before execution, I like to display the options to the user, so that they know that the program knows what they meant by the command-line options.
Here's the code that does that:
private static void printObject(object obj)
{
PropertyInfo[] pia = obj.GetType().GetProperties();
foreach (PropertyInfo pi in pia)
{
Console.WriteLine(
pi.Name.PadRight(16, ' ') +
": " +
pi.GetValue(obj, null).ToString());
}
}
This could, of course, be used for any scenario where you want to inspect the values of the properties on an object. If you were so inclined, this could easily be expanded to have a lot more detail, handle arrays, print the type name of the object, etc.. I have various permutations of this method that do some or all of that as needed. I have considered turning this into a class with all those fiddly bits configurable, but haven't gotten around to it yet.. If I ever do, I'll post it here!
2007-06-08
IComparable and Egocentrism
While her stance is in many ways similar to my own thinking, I still felt compelled to consider how I would respond if I were having the conversation with her... It would go something like this...
Why do we put such a fine point on our differences? Why do we go to war over skin colours, eating habits, clothing choices, and other such nonsense? Because human beings are intrinsically scared shitless of sameness. Internally, we must compare everything. We are so bound up in the process of comparison logic, that it permeates our every action. Is this bad or good? Better or worse? Bigger or smaller? Subordinate or superordinate? Our base class is IComparable.
These thoughts consume our lowest level drives.. To be a good person.. To get ahead in life... To be comfortable (as opposed to NOT comfortable, and any degree of comfortable is better than any degree of uncomfortable). To be powerful.. not just powerful, but specifically more powerful than you were before, or more powerful than the other guy.
So we focus on our differences, because through our differences we can find something, ANYTHING to make us special, better, to return 1 on our .CompareTo() call for at least one property.
This got me to thinking about the implementation of IComparable in .NET/C#. Isn't it quite egocentric? To presume that the scope of knowledge within a single object type is sufficient to allow it to be compared to any other type? To consider that I know how to compare myself to any other thing, even if I don't know what that thing is? That notion is quite absurd. What I find interesting about the implementation is the .CompareTo() takes an untyped object as a parameter. Doesn't it follow that an object of a given type should only be able to compare itself to something else of the same type? That in order to compare to an object of some other type it must at least be able to be converted to that type first, so that it can be compared on equal terms?
There's a lot of discussion about that implementation. It could be argued that it's valid, but nonetheless, it's completely egocentric. How do you resolve a scenario, where both foo.CompareTo(bar) and bar.CompareTo(foo) both return 1? Which one sorts higher in the call to SortedList.Sort()? or do they simply not change position relative to one another ever? So first come first serve?
What if IComparable worked differently? I envision it this way... Image a static object called System.Judge. System.Judge has a method .Compare which takes any two objects that implement IComparable. The interface for IComparable requires the object to maintain a property .CompareValues which contains a list of all the values it maintains that it is willing to offer up during comparison, organized by Type, Name, Value. The Judge accesses foo.CompareValues.Types to get a list of types that it is willing to be compared to. Judge calls that from both objects, until it finds a list of compatible types to start comparison with. For all comparable matching types, a comparison result is achieved, and then an average of comparison is evaluated, and the object with the highest average of comparison success is considered the victor. The .CompareTo call would naturally be nested calls on the various IComparable types presented until finally a value type with a fixed, built-in comparision method is found and stops the nesting compare calls.
This sytem would of course be more complicated, and require a lot more processing for each call, resulting in much slower performance.. Ah but the logic would be sound, and that, my friends, is much more valuable than processing time.
Good night.
2007-05-31
Disable Design-Time Support in Visual Studio
public class MyShellTask : Process
{
...
}
One thing that bugged me to no end is that, in Visual Studio, when you double click the file in the Solution Explorer, it considered it "designable" even though there was no designer. So that means I got a empty page every time, telling me that it was not designable, with a link to "View Code". Well, "View Code" is what I wanted, not "View Designer", when I double-clicked!
So after getting very frustrated, I did the natural thing.. I googled looking for an answer. I had a notion that I could control this behaviour through Attribute tags on the class if only I knew the right one. Having made designable components before I was familiar with the attributes used for that. I tried fiddling about with Intellisense, Googling, all to no avail.. Nothing worked! Nothing showed up in my Google searches! Good God! What to do now?
Fiddle some more... until finally I found the right attribute:
[System.ComponentModel.DesignerCategory("")]
public class MyShellTask : Process
{
...
}
Note that you must call this with an empty string (don't believe the intellisense comment, an empty constructor call will NOT do the same as calling the constructor with an empty string.) This sets it to a non-category that it doesn't know how to deal with, and so doesn't offer designer support to you!
This also helps custom installer class for use with your Visual Studio Setup projects, which exhibit the same annoying VS UI problems... ie:
///
/// Custom Installer actions for this project.
///
[RunInstaller(true)]
[System.ComponentModel.DesignerCategory("")]
public partial class MyInstaller : Installer
{
...
}
Hope that helps someone! Now there will be at least ONE hit if someone googles up "disable design-time support" or "disable designer support" like I did!
2007-05-09
Java, NetBeans, and Templates, OH MY!
Having never programmed in Java before, but understanding it's really similar to c# (or I should say c# is really similar to Java), I immediately started fiddling about as if I were writing c# code. So, it's easy to get past typing uppercase String, not lowercase, and also not too hard to grok "extends" instead of ":" for inheritance. The one-class-per-file thing, well, I guess it will just make me a more organized programmer, however annoying it is. But the things that really erked me was properties.
In c# I can do this:
...
private string _name;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
...
but in Java, that looks like:
...
private String _name;
public String getName()
{
return this._name;
}
public void setName(string value)
{
this._name = value;
}
...
Wow. Extremely obnoxious. Furthermore, I have finally gotten myself broken in with the VS2005 IDE to type "prop" + TAB to get a nice template for my properties. Well, since there is no such thing in Java, this macro also does not exist. So, I proceeded to make a NetBeans code template called "prop", which functions the same way the VS2005 "prop" code snippet does.
So, for all you c# coders who are venturing into the foreign lands of Java, here's a little tutorial on how to add this little cultural comfort into NetBeans.
Property Code Template Installation Instructions:
1. Select menu item "Tools->Options".
2. Click on "Editor" sidebar button.
3. Click on "Code Templates" tab.
4. Select "Java" from languages combo-box.
5. Click "New", and then enter "prop" as the Abbreviation in the dialog.
6. Click "Ok".
7. Make sure "prop" is the selected template, and in the text box below the list, enter these lines:
private ${int} ${_prop};
public ${int} get${Property}()
{
return this.${_prop};
}
public void set${Property}(${int} value)
{
this.${_prop} = value;
}
8. Select "Tab" from "Expand On" combo box.
9. Click "OK".
Now you've got it installed.. Feel free to go to the code and give it a whirl! Have a look at the other macros in the list to see what's built in, and once you figure out the syntax of the template notation, make your own templates!
2007-02-16
Code Snippet: ListEnum
private static void ListEnum(Type _enum)
{
Console.WriteLine("enum " + _enum.Name);
Console.WriteLine("{");
string[] foo = Enum.GetNames(_enum);
Array bar = Enum.GetValues(_enum);
for(int i =0;i<foo.Length; i++)
{
Console.WriteLine(
foo[i] + " = " +
((int)bar.GetValue(i)).ToString() + ",");
}
Console.WriteLine("}");
}
Enjoy!
2007-02-14
Code Snippet: SQL FileExists
The first method I tried for doing this used an undocumented system stored procedure in MSSQL, called xp_fileexist. The code for that looks like this:
-- using MSSQL built-in stored proc xp_fileexist
CREATE FUNCTION FileExists(@File varchar(255)) RETURNS BIT AS
BEGIN
DECLARE @i int
EXEC master..xp_fileexist @File, @i out
RETURN @i
END
It's a pretty simple wrapper around the stored-procedure. Implimenting it as a function provides a more versatile tool for querying howver, as shown in this example usage:
--- usage
SELECT *
FROM tbl_FileInformation
WHERE (dbo.FileExists(PathAndFile) = 'True')
Unfortunately, this didn't do the trick for us at that time. MS SQL server apparently cannot, under any circumstances, see mapped drives. All of our data was on a drive called 'P:', which was mapped to a network accessible storage device, that our whole company uses. Not to be discouraged, I thought to myself "Well, perhaps it's just a limitation of the xp_cmdshell options, not SQL server as a whole. May there's another way of finding this out...".
So that led me to write this next function, which uses Scripting.FileSystemObject via the OLE Automation Options. First things first, I needed to run the following commands to enable OLE Automation, to make it possible:
-- configuring for use of scripting object
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
That's the SQL native way, the other option is to use Surface Area Configuartion and enable it via the check-box. Once that was out of the way, I could try out my function...
-- Using the scripting object
CREATE FUNCTION FileExists(@File varchar(255)) RETURNS BIT AS
BEGIN
declare @objFSys int
declare @i int
exec sp_OACreate 'Scripting.FileSystemObject', @objFSys out
exec sp_OAMethod @objFSys, 'FileExists', @i out, @File
exec sp_OADestroy @objFSys
return @i
END
But... unfortunately, this gave the same results.
So, the moral of the story? Kids, MS SQL just can't see mapped drives. Give it up now!
If you're lucky enough to have all your data on a drive that's local to the SQL server, and find yourself needing to know if a file you've got referenced still exists, then give these methods a try!
YMMV.
2007-02-08
vista sidebar on XP 2
It turns out the patched version of the Sidebar executable is from a early beta version of Vista. The unfortunate point about that, is that the Gadgets that work with the XP version are vastly different than the Gadgets for the released version of Vista. That means all the gadgets that you can download don't work with the XP version. It also means that all the information about developing Gadgets for the Sidebar is relevant to the Vista version, not the XP version.
To detail some of the differences:
In the early release, Gadgets are not even called Gadgets, they are called Parts. Parts and Gadgets are very similar, in that they both are a zip file containing what amounts to a mini-webpage which is loaded and interpreted by the Sidebar.
In the XP version, a Part is a zip file with the extension changed to ".part", in Vista the extension is ".gadget". In XP, the directory where those files are stored is %userdir%\Parts, in Vista it's %userdir%\AppData\Local\Microsoft\Windows Sidebar\Gadgets.
Parts require a Manifest.XML file, while Gadgets require a Gadget.xml file. The contents of those files, while containing nearly the same data, use different names for all the tags, making them not compatible.
Beyond that there are a number of other subtle differences, as well as a generally limited set of functionality in the XP version, as compared to the released Vista version.
So, that poses a question? Considering the large amount of people who aren't interested in upgrading to Vista, due to performance or cost issues, or just not wanting to uproot and start again, is it worth my time to develop for this patched version of the Vista sidebar? Is there a substantial user-base that would benefit from having more cool Gadgets, I mean Parts, to run in their XP Patched Vista Beta Sidebar?
Perhaps that's a bigger niche than one would initially imagine.
Well, until I have an install of Vista to run the release version, providing a development environment for generating good Gadgets, I may just amuse myself with by playing with potentially pointless Parts.
vista sidebar on XP
The reason for this is that, I, being slightly conservative regarding willy-nilly-ly installing new OSes as soon as they are available, choose to upgrade by force, only when absolutely unable to do otherwise. That means, I'm running Windows XP. So what is a developer to do now that his interest is piqued? Install Vista so I can play with Gadgets and the mystical sidebar? No! I, of course, choose to google up a nice patched version of sidebar.exe that can run on XP!
Woohoo! I'm excited to say, that this not only works, but works without a hitch. I was able to install and run the Vista Sidebar on XP in mere moments. And that also means I can fiddle with widgets, oops I mean Gadgets. ;)
See my next few posts for more information about Gadgets... But before you do, download the XP version of Windows Sidebar so you can join in the fun too!
Links and knowledge courtesy of MSTN and their article about this, which I found out about by reading this blog post on My Digital Life.
2007-02-07
self-stabilization and dijkstra
His first reaction was "that's sort of militant". Probably in reference to the term "vanguard" which is generally used to refer to an aggressive front-line force of some sort. I concurred, but still felt I had made a good choice.
Max then immediately hijacked my computer, launched a new firefox window, and began googling up and mumbling unrecognizable names. Dijkstra, The Humble Programmer, and How do we tell truths that might hurt? suddenly appeared and were read out-loud to me by my excited friend and companion.
He was right!
How fascinating was Dijkstra? Fascinating enough that, even though I had worked 13 hours straight, eaten almost nothing all day, and have a beautiful wife and 1.5 week old child waiting for me, I felt compelled to click about and read more.
I came across self-stabilization and it occurred to me, that the impetus behind creating this blog is a form of self-stabilization. In one sense, it's my own self-stabilization, in which I will divest and store the processes by which I created order from confusion in my daily life, providing a resource which I could use to reduce the amount of overhead needed to repeat these feats. But secondly, it is self-stabilization as and unconscious process of the online tech-blogging community. I rely heavily on the blogged accounts of problem-solving that others so diligently post for all the world to see. The first thing I do when I encounter a new and challenging problem is to check and see who has dealt with this problem before, and what did they do? What solutions are already available in the vast spray of information available from public search engines? Most of the valuable information I find is not the official formal documentation provided by the institutions that created the technologies, detailing every facet of the system with excrutiating thoroughness, but rather the anecdotal, code-snippetted, hyper-linked, semi-stable accounts posted by my unknown peers battling the same dragons. From these bits, I learn how to use the vast and morbid technology describing in the aforementioned chronicles of specificata.
So this blog, is self-stabilization for the blogging culture in which I so heavily rely. If there were no blogs to read, how would I solve many of those problems? Isn't it my duty to give back to that system? Shouldn't I also serve to stabilize this information vortex and let other reap from my trouble-shooting bounty?
Indeed. I should.