Implementing Mouse Hover in WPF

We’ve spent the past couple of weeks at work giving ourselves a crash course in Windows Presentation Foundation (WPF) and LINQ.  I’m working on a code example that will switch the datatemplate in a list item when the mouse hovers over it.  Unfortunately, WPF has no MouseHover event like Windows Forms does.  The usual googling didn’t cough up a ready-made answer.  Some hacking on one example did reveal a half-answer (not ideal, but at least a start).

First, I set the ToolTip property of the element I used to organize my data (in this case, a StackPanel).  Next, I added a ToolTipOpening event for the StackPanel.  Here’s the code for StackPanel_ToolTipOpening:

private void StackPanel_ToolTipOpening(object sender, ToolTipEventArgs e)
{
e.Handled = true;
ContentPresenter presenter = (ContentPresenter)(((Border)((StackPanel)e.Source).Parent).TemplatedParent);
presenter.ContentTemplate = this.FindResource("Template2") as DataTemplate;
}

The result: instead of a tooltip displaying when you hover over a listbox row, the standard datatemplate is replaced with an expanded one that displays more information.  This approach definitely has flaws.  Beyond being a hack, there’s no way to set how long you can hover before the templates switch.

Switching from an expanded datatemplate back to a standard one involved a bit less work.  I added a MouseLeave event to the expanded template.  Here’s the code for the event:

private void StackPanel_MouseLeave(object sender, MouseEventArgs e)
{
ContentPresenter presenter = (ContentPresenter)(((Border)((StackPanel)e.Source).Parent).TemplatedParent);
presenter.ContentTemplate = this.FindResource("ScriptLine") as DataTemplate;
}

So once the mouse moves out of the listbox item with the expanded template, it switches back to the standard template.  Not an ideal solution, but it works.

This link started me down the path to finding a solution (for reference).

Free Test Data

If you find yourself in need of test data (and if you write software for a living, you’ve got that need pretty often), pay a visit to generatedata.com.  You have your choice of five different result formats: HTML, Excel, CSV, XML, and SQL.  If you’re using it for free, you’re limited to 200 rows of test data.  Donate $20 or more and the limit increases to 5000 rows.  If you don’t mind fiddling with PHP and MySQL, you can download the generator for free and set it up on your own server.

Comparing XML Strings in Unit Tests

Comparing two XML strings is painful.  So of course, my current project required me to come up with a way to do it in .NET.  I could only use version 2.0 of the framework, and I didn’t want to add more dependencies to solution that already has plenty (which ruled out XML Diff and Patch).  So far, I’ve come up with the following bit of code:

The validationXml contains a string representation of the XML being validated against.  It also means I only have to create one instance of XmlDocument.  After creating an XPathNavigator on the XmlDocument being compared,  an XPathExpression for the subset of XmlDocument being validated, and an XPathIterator, it can be called.

The “params” keyword makes the last argument optional, so it can contain zero or more names of XML elements to ignore when deciding whether or not to call an Assert.  I’m still figuring out how to optimize this, but I think it’s a good start.

Converting File URIs to Paths

I spent most of this morning looking for a replacement to Application.ExecutablePath.  The reason for this was because certain unit tests that depended on this code failed when a used any test runner other than the NUnit GUI.  When using test runners like ReSharper and TestDriven.NET, Application.ExecutablePath returned the executable of the test runner, instead of the DLL being tested.

Assembly.GetExecutingAssembly().CodeBase returned a file URI with the DLL I wanted, but subsequent code which used the value threw an exception because it didn’t accept file URIs.  This made it necessary to convert the file URI into a regular path.  I haven’t found a .NET Framework method that does this yet, but the following code seems to do the trick:


private static string ConvertUriToPath(string fileName)
{
fileName = fileName.Replace("file:///", "");
fileName = fileName.Replace("/", "\");
return fileName;
}

My Two Cents on Reinventing the Wheel

Yesterday, I came across a spirited defense of reinventing the wheel in a recent post from Jeff Atwood.  Dare Obasanjo stands firmly in the “roll your own as last resort” camp.  In this particular case, Atwood asserts the following:

[D]eeply understanding HTML sanitization is a critical part of my business.

I’ll take Atwood at his word on what’s critical to his business (and what isn’t), but it seems that there’s a middle ground between his position and Obasanjo’s.  Particularly when there’s an open source solution available (SgmlReader in this case, since it’s written in C#), adopting and improving it has these benefits:

  • Improved understanding of HTML sanitization for the adopter.
  • Strengthening of the existing community.

To Atwood’s credit, he’s made his solution available here so that all of us who write software for a living can benefit from it.  I would be very interested in seeing a comparison between the SgmlReader and Atwood’s HTML Sanitizer to see which is better.

My own experience with reinventing the wheel (in software development terms) has rarely, if ever, been positive.  Therefore, I have a lot of sympathy for Obasanjo’s perspective.  Because I’ve inherited a lot of software from predecessors at various employers, I’ve seen a lot of less-than-ideal (to put it kindly) custom implementations of validation, encryption, search and logging functionality.

There are probably plenty of reasons that development teams reinvent the wheel in these areas, but one highly likely (and unfortunate) reason seems to be insufficient awareness about the wide variety of high-quality open source solutions available for a variety of problems.  I don’t know whether this is actually more true in internal IT shops than other environments or not, but it seems that way.  Encryption and logging in particular are two areas where it seems like custom code would be a bad idea for virtually everyone (except those actually in the encryption and logging library businesses).  With libraries like log4j, log4net, the Enterprise Library, and Bouncy Castle available, developers can spend their time focusing on what’s really important to their application.  Code for authentication and authorization seems like one of those areas as well.  It seems like there are a lot of solutions to this problem (like OpenID on the public web, and Active Directory in the enterprise) that time spent hand-rolling login/password anything is time not spent working in areas where more innovation is possible (and needed).

When I asked the question of “what should always be third-party” to Stack Overflow, I got some interesting answers.  Most answers seemed to agree that encryption should be third-party, except in rare cases, but there was surprising little consensus beyond that.  Beyond the scarce resources argument against custom logging (or other areas with widely available open source alternatives), there’s a diminishing returns argument as well.  I’ve only used Log4Net and the logging in the Enterprise Library, but they’re really good frameworks.  Even if I had the resources to implement custom logging well, the odds that the result would be a significant improvement over the existing third-party options are slim to none.  I’d like to see the quality argument made more often in buy vs. build decisions.

Stack Overflow is Live

Stack Overflow is a great new programmer Q & A site from Jeff Atwood and Joel Spolsky.  I (and about 500 other developers) got a 5-week headstart on using it as part of the private beta test.  As good as googling for answers to development problems has been, Stack Overflow is a big improvement.  I’ve already gotten answers to questions that I was able to use in my own work.

If you write code for a living, I strongly encourage you to check out the site.  They support OpenID, so you can use your existing Yahoo! or Blogger (other other OpenID-compliant) identity to register with the site.  You can use it anonymously as well.

Granting full permissions to all tables and views in a database

One of my assignments is to write a script that will grant CRUD (create, read, update, delete) permissions to a database role.  SQL Server Management Studio does a nice job of generating scripts for adding logins, roles, and adding users to roles, but isn’t terribly clever about granting permissions across types of database objects.  Some of the difficulty has to do with not having upgraded to SQL Server 2005 yet.  Thanks to some helpful people at Stackoverflow and a page I found through a Google search, I was able to put together a script that handles the permission-granting part a bit better.

Step 1 was to develop a query that generated all the commands for granting permissions.  Here’s the query I got from Stackoverflow that retrieved all the user tables and views:

SELECT * 
FROM information_schema.tables 
WHERE OBJECTPROPERTY(OBJECT_ID(table_name),’IsMSShipped’) = 0

This query is especially useful because it filters out system tables and views that can appear if you query the sysobjects table.

Using a cursor to apply permissions to all the tables was something one of my colleagues first suggested.  I only found this implementation today, and adapted it for my purposes.  The change I made to the code in that implementation is in the select statement.  I populated the @tables variable this way:

SELECT ‘GRANT SELECT, REFERENCES, INSERT, UPDATE, DELETE ON ‘ + TABLE_NAME + ‘ TO ‘ + @role
FROM information_schema.tables
WHERE OBJECTPROPERTY(OBJECT_ID(table_name),’IsMSShipped’) = 0 

@role is declared earlier in my script as varchar(50).

I still need to grant execute permissions on the stored procedure.  I’ll need a different select query to accomplish that.