Aug 31, 01:47 PM
The Visual Studio Find and Replace dialog is often overlooked, and when parts of it are looked at (Regex searching) it often gets a bad rep. Sure it doesn’t implement all of the Regex syntax (non greedy search springs to mind), but that’s not to say it isn't useful.
For instance, I was working on some code that involved a Model View Presenter type style, but used Subroutines (void methods) rather than WriteOnly properties for brevity (in C# you can do a Set only property in 1 line, VB it takes 5). As the View is doing nothing other than assigning labels from these "Setters" who cares how many lines it takes?
A quick breakdown of the parts of the expressions used:
Finding:
{} //Tag an expression, used in replacements. Numbered sequentially from 1, not 0.
(.*) //Any character, any number of times, as many as possible.
\ //escape character, allows us to search for a literal '.' or other Regex used symbol.
Replacing:
\1 //The content of a tagged expression.
\n //New line
\t //Tab (although after running all these find and replaces, a quick {CTRL+E, CTRL+D} (format document) does most of the tidying for you).
So we start with the Interface:
Public Interface IProcessDetailsView
Sub FileID(ByVal value As Integer)
Sub SubmittedBy(ByVal value As String)
Sub ReceivedDate(ByVal value As DateTime)
//...
End Interface
So in the find and replace dialog I enter the following:
Find what:
Sub {(.*)}\(ByVal value As {(.*)}\)
Replace with:
WriteOnly Property \1() As \2
The interface definition now changes to this:
Public Interface IProcessDetailsView
WriteOnly Property FileID() As Integer
WriteOnly Property SubmittedBy() As String
WriteOnly Property ReceivedDate() As DateTime
//...
End Interface
Not too difficult right? Good. Now onto the View's methods:
Public Class ProcessDetails
Implements IProcessDetailsView
Public Sub FileID(ByVal value As Integer) Implements IProcessDetailsView.FileID
lblFileID.Text = value.ToString
End Sub
Public Sub SubmittedBy(ByVal value As String) Implements IProcessDetailsView.SubmittedBy
lblAccountName.Text = value
End Sub
//...
End Class
Into the find and replace dialog:
Find what:
Public Sub {(.*)}\(ByVal value As {(.*)}\) Implements IProcessDetailsView\.(.*)
Replace with:
Public WriteOnly Property \1() As \2 Implements IProcessDetailsView.\1\n\t\tSet(ByVal value As \2)
Find what:
End Sub
Replace with:
End Set\n\tEnd Property
You could do this with one expression, although I have found its far less hassle to use two find and replace runs rather than trying to find new lines etc
Public Class ProcessDetails
Implements IProcessDetailsView
Public WriteOnly Property FileID() As Integer Implements IProcessDetailsView.FileID
Set(ByVal value As Integer)
lblFileID.Text = value.ToString
End Set
End Property
Public WriteOnly Property SubmittedBy() As String Implements IProcessDetailsView.SubmittedBy
Set(ByVal value As String)
lblAccountName.Text = value
End Set
End Property
End Class
Now the main reason for this change was the presenter code, which doesn’t sit right with me. At a glance, am I expecting something to be calculated or what?
Public Sub Display(ByVal processHistory As ICVProcessHistory)
_view.FileID(processHistory.FileID)
_view.SubmittedBy(processHistory.AccountName)
//...
End Sub
Find and replace dialog again:
Find what:
\_view\.{(.*)}\({(.*)}\.{(.*)}\)
Replace with:
_view.\1 = \2.\3
Which gives us this:
Public Sub Display(ByVal processHistory As ICVProcessHistory)
_view.FileID = processHistory.FileID
_view.SubmittedBy = processHistory.AccountName
//...
End Sub
Much better in my opinion.
— Andy
Code, .net
Mar 24, 11:03 AM
Multilining if statement conditions is bad. I was modifying some code and came across this:
If String.IsNullOrEmpty(_selectedGUID) OrElse _
_selectedGUID = FeeAgreement.GetDefaultContractAgreementGuid OrElse _
_selectedGUID = FeeAgreement.DefaultPermAgreementGuid Then
fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
_selectedTitle = ag.Title
_lastIndexRowSelected = rowAdded
End If
Which at a glance looks like this:
Single Line If
Variable Assignment
Variable Assignment
One person suggested that if someone had to do multiline the condition they could at least indent it. That’s not much good either though:
If String.IsNullOrEmpty(_selectedGUID) OrElse _
_selectedGUID = FeeAgreement.GetDefaultContractAgreementGuid OrElse _
_selectedGUID = FeeAgreement.DefaultPermAgreementGuid Then
fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
_selectedTitle = ag.Title
_lastIndexRowSelected = rowAdded
End If
Looks like this:
If Condition Then
Variable Assignment
Variable Assignment
You could one line the whole thing, which while I think is better than multi line conditionals, still isn't great as I cant see all of it on a normal sized screen (read "work supplied screen").
If String.IsNullOrEmpty(_selectedGUID) OrElse _selectedGUID = FeeAgreement.GetDefaultContractAgreementGuid OrElse _selectedGUID = FeeAgreement.DefaultPermAgreementGuid Then
fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
_selectedTitle = ag.Title
_lastIndexRowSelected = rowAdded
End If
So, Why not just do it as suggested in Code Complete, which fits on my screen and explains the comparisons:
Dim isContract As Boolean = (_selectedGUID = FeeAgreement.GetDefaultContractAgreementGuid)
Dim isPerm As Boolean = (_selectedGUID = FeeAgreement.DefaultPermAgreementGuid)
If String.IsNullOrEmpty(_selectedGUID) OrElse isContract OrElse isPerm Then
fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
_selectedTitle = ag.Title
_lastIndexRowSelected = rowAdded
End If
I don’t know who wrote the above original code, and I don’t much care either.
I do however think that the people who like the original style are clinically insane...and I work with at least one like this!
Some unit tests wouldn’t go amiss either. Well, tests of any kind would be a good start...
— Andy
Bug, Code, .net
Jan 12, 06:52 AM
While this is not something I personally would want to do, we (for whatever reason...) are to use MSTest at work (I think it is due to the whole "Its Microsoft, so it’s supported" argument).
Now as no one else on the team does any kind of unit testing (serious), the only test projects we have are written by me, on the quiet before being told if I wanted to unit test then use MSTest. So onto the point of this article.
When you create a project for tests with nunit, you just create a Class Library, add a reference to nunit (and Rhino.Mocks of course), build it and run with your preferred method (I like TDD.Net, but that involves paying for at work...so no go there).
When you want to do tests with MSTest, you just create a Test Project and start writing tests. On closer inspection, it’s just a Class Library with a reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework. So converting one to the other should be easy, right?
Well not quite. While there is nothing in the GUI to suggest so, you need to modify the csproj/vbproj file to get it to work. This post on MSDN, had all the details, but in the interest of having things in more than one place (not very DRY I will admit, but there), here are the steps:
- Remove Reference to Nunit.Core & Nunit.Framework
- Add Reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework
- Find and Replace:
using NUnit.Framework; with using Microsoft.VisualStudio.TestTools.UnitTesting; (I actually use a project level import, so I skip this)
- [TestFixture] -> [TestClass]
- [Test] -> [TestMethod]
- [SetUp] -> [TestInitialize]
- [TearDown] -> [TestCleanup]
- [TestFixtureSetUp] -> [ClassInitialize]
- [TestFixtureTearDown] -> [ClassCleanup]
- Change your Asserts:
- Assert.Greater(x, y) -> Assert.IsTrue(x > y)
- Assert.AreEqual(x, Is.EqualTo(y).IgnoreCase) -> Assert.AreEqual(x, y, True)
- The 'hidden' part. In your project file, locate
<PropertyGroup> (not the one specifying debug|release settings), and add the following to it:
- 512
- *.csproj files add:
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
- *.vbproj files add:
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
This was all I had to do to get our (my) tests running again under MSTest. Except they didn’t run, with the lovely error of:
The location of the file or directory 'D:\Projects\Dev\SDK\Rhino.Mocks.dll' is not trusted.
That’s odd, the file is on my hard disk, its not a network share, so what’s the problem? Right click on Rhino.Mocks.dll and:

Click the button, hit Apply, re-run the tests. All Working now :)
There are a few other points mentioned on the MSDN post too which you may run into:
If you have relied on NUnit TestFixtureSetup and TestFixtureTearDown methods to do non-static things, will have to move functions in the former to a constructor and the latter to a destructor. In MSTest, both of these methods must be declared as static.
If you are relying on AppDomain.CurrentDomain.BaseDirectory to get the root directory, your test will break. The fix is explained at http://www.ademiller.com/blogs/tech/2008/01/gotchas-mstest-appdomain-changes-in-vs-2008/. Basically, you need to set your BaseDirectory in your MSTest TestClass constructor like this:
string currDir = Environment.CurrentDirectory.Substring(0, Environment.CurrentDirectory.IndexOf("TestResults"));
AppDomain.CurrentDomain.SetData("APPBASE", currDir);
MSTest launches each test method in a separate STA thread instead of the MTA thread you may be expecting. This probably won’t give you any problems.
Hope that helps everyone who has to do this kind of conversion.
— Andy
Code, .net
Dec 16, 12:06 PM
Following on from yesterday's post about separation on concerns and where to put some undefined logic for a multi state checkbox, I did a fair amount of research.
I must say the Quince website is a good repository of UI Design Patterns, as is Welie. I couldn’t find anything like what I was after, which I guess means I shouldn’t be doing it this way?
After a while a brainwave struck me: "Gmail lets you select things, how does it do it?” One click on the Gmail icon and I'm presented with this:

Perfect. So I went back to my sponsor and showed them a mock-up with this style of selection. The reaction was: "Oh I like that". Excellent news, for me its easier code to write (I’m happy with a for loop setting a grid cell to true in the view) and if they want to add other selections its easy enough (though there is not much else they could select by...).
The moral of the story? If in doubt, copy Google.
— Andy
Code, Design, .net
Dec 15, 12:37 PM
When I am writing a winform in a MVP style, I often wonder how far to go with the separation. Say I have the following situation:
A Small form which should display a list of messages, and allow the user to select which ones they want processed. It processes each message in turn. If a message has more than one attachment, a dialog is shown to ask the user to select which attachment should be used for that message.
Now while this is fairly simple, my interface for the message dialog looks like this:
Public Interface IMessageSelector
Event Submit()
Event Cancel()
WriteOnly Property Messages() As IList(Of MessageData)
ReadOnly Property Selected() As IList(Of String)
ReadOnly Property AttachmentView() As IAttachmentScreen
Sub ShowScreen()
Sub CloseScreen()
Sub DisplayWarning(ByVal text As String)
End Interface
In the form I have (roughly) the following:
Public Class frmMessages
Implements IMessageSelector
'...'
Public WriteOnly Property Messages() As IList(Of MessageData) Implements IMessageSelector.Messages
Set(ByVal value As IList(Of MessageData))
For Each d As MessageData In value
Dim r As Grid.Row = grid.Rows.Add
r("id") = d.ID
r("subject") = d.Subject
r("from") = d.Sender
r("received") = d.SendDate
Next
flx.AutoSizeCols()
End Set
End Property
Public ReadOnly Property Selected() As IList(Of String) Implements IMessageSelector.Selected
Get
Dim result As New List(Of String)
For i As Integer = 1 To grid.Rows.Count - 1
If Convert.ToBoolean(grid(i, "selected")) Then
result.Add(grid(i, "id").ToString)
End If
Next
Return result
End Get
End Property
End Class
Now I think that this is ok. There is not logic as such in the population property, and the Selected property just determines which rows have had their checkboxes ticked.
However it has been requested that I add a 'Select All/None' checkbox to the form. Where do I add the code for this? As they want a checkbox to tick or detick its not as trivial as it could be. If it were separate buttons, I could just use a for loop in each setting the values to True or False. A checkbox however has some uncertainties:
- Checking the master checkbox should make all rows checked. Fine.
- DeChecking the master checkbox should make all rows unchecked. Also fine.
- Checking one row when none are checked should do what to the master checkbox?
- DeChecking one row when all are checked should do what to the master checkbox?
- 25%/50%/75% of rows are checked, what does the master checkbox look like?
- Some rows are checked. What happens when the checkbox is clicked?
So many questions for such a simple looking feature. With so many possibilities for it maybe it should go into the presenter/interface? At least it’s testable then. Maybe a separate controller for it as it’s not really anything to do with the purpose of the form?
If anyone knows of answers to this I would be very interested to hear them.
— Andy
Code, Design, .net