<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://soapitstop.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>.NET Flea Market</title><link>http://soapitstop.com/blogs/fleamarket/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP2 (Build: 20611.960)</generator><item><title>User-Selectable Multiple Instance Application</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/12/23/user-selectable-multiple-instance-application.aspx</link><pubDate>Wed, 23 Dec 2009 13:58:05 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:287</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=287</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/12/23/user-selectable-multiple-instance-application.aspx#comments</comments><description>&lt;p&gt;Visual Studio.NET allows you to set a property that makes your application a single-instance application, where double-clicking the icon while the app is running simply brings the already-running app to the foreground.&amp;#160; But what if you wanted the option of having multiple instances, say for power users?&amp;#160; Well, you could start by creating an application setting, so you have My.Settings.AllowMultipleInstances to work with.&amp;#160; But now where do you set it?&amp;#160; &lt;/p&gt;  &lt;p&gt;Visual Studio allows you to patch in to application events.&amp;#160; Click the View Application Events button in the application properties page and a new file is created: ApplicationEvents.vb, which is a partial class extending the MyApplication class.&amp;#160; We can see that there are some events we can hook into. The Startup event appears to be the first event, so we put our code in there: &lt;/p&gt;  &lt;p&gt;Me.IsSingleInstance = Not My.Settings.AllowMultipleInstances&lt;/p&gt;  &lt;p&gt;And when we run the app, we see that it doesn’t make any difference.&amp;#160; Apparently we are setting the property too late.&amp;#160; Ok then, we need to move up the ladder.&amp;#160; There is a file buried in the My Project section called Application.Designer.vb.&amp;#160; There is a line in the constructor there that reads Me.IsSingleInstance=True (or false, depending on how you have it set).&amp;#160; So we can set that value to the AllowMultipleInstances setting.&amp;#160; And when we run the app this time, we end up with a stack overflow error.&amp;#160; Why?&amp;#160; As it turns out,&amp;#160; while you are in the constructor of the MyApplication class, you are creating an instance of the MySettings class, which wants an instance of MyApplication, which isn’t done being constructed yet.&amp;#160; So they go back and forth trying to get instances of each other and cause a stack overflow.&amp;#160; Ok, the constructor is off-limits, then.&amp;#160; Besides, that file is auto-generated and you’d lose that change the next time you made any change through the Visual Studio property page.&amp;#160; &lt;/p&gt;  &lt;p&gt;Well, crap.&amp;#160; The provided events are too late and the constructor is too early.&amp;#160; There’s no other entry points.&amp;#160; Not true!&amp;#160; This is one of those things that VB programmers can do that C# programmers can’t.&amp;#160; And of course C# snobs would just say “that’s poor coding”, but they’re just jealous.&amp;#160; You can shadow the Run method in the WindowsFormsApplicationBase class, which is where the logic is that handles single/multiple instances.&amp;#160; So in the ApplicationEvents.vb file, where you can extend the MyApplication class, add:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Public Shadows Sub Run(ByVal commandLine() As String)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Me.IsSingleInstance = Not My.Settings.AllowMultipleInstances      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; MyBase.Run(commandLine)      &lt;br /&gt;End Sub&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;And now you can switch between single and multiple instance application settings.&amp;#160; All we did was inject an extra line of code in the Run method, which is after the constructor but before the Startup event.&lt;/p&gt;  &lt;p&gt;Wow, I’ve been blogging for over 2 years?&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=287" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Troubleshooting/default.aspx">Troubleshooting</category></item><item><title>The Holidays Are All About Money</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/12/20/the-holidays-are-all-about-money.aspx</link><pubDate>Sun, 20 Dec 2009 16:43:16 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:286</guid><dc:creator>anachostic</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=286</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/12/20/the-holidays-are-all-about-money.aspx#comments</comments><description>&lt;p&gt; No, this post isn’t a rant on consumerism and lack of true holiday spirit.&amp;#160; I have another blog for that.&amp;#160; This is my programming blog.&amp;#160; I was thinking hard about what I could post to close out the year.&amp;#160; It doesn’t seem much has been happening.&lt;/p&gt;  &lt;p&gt;But I recently moved from MS Money to Quicken and some of the changes between the two are a little jarring.&amp;#160; The biggest difference is in the register, where the running balance only calculates the displayed transactions.&amp;#160; So if you filter the view by date or status, the running balance has no useful meaning.&amp;#160; I find this flaw infuriating, as do other former Money users, but Quicken users have dealt with it from the introduction of register filters.&lt;/p&gt;  &lt;p&gt;So, me being the “oh, it can’t be that hard” kind of person, I decided to test the waters and see how difficult it would be to re-write MS Money in .NET.&amp;#160; Aside from a lot of the financial rules and calculations used in the investments section, I’m not discouraged yet.&amp;#160; Last night I went through the screens in Money and whipped up some basic object diagrams.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://soapitstop.com/blogs/fleamarket/Accounts_47F19061.gif"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="Accounts" border="0" alt="Accounts" src="http://soapitstop.com/blogs/fleamarket/Accounts_thumb_120C9B47.gif" width="536" height="480" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://soapitstop.com/blogs/fleamarket/Transactions_1134355D.gif"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="Transactions" border="0" alt="Transactions" src="http://soapitstop.com/blogs/fleamarket/Transactions_thumb_45685EA3.gif" width="549" height="480" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And then I started working on some conceptual programming ideas to make sure I wouldn’t hit a wall.&amp;#160; The first thing I wanted to make sure I could handle was a running balance in the register.&amp;#160; It must be pretty difficult if Quicken can’t do it.&lt;/p&gt;  &lt;p&gt;I thought about all the different ways a register would be modified and the effect of those changes.&amp;#160; But there was one difference between Quicken and Money that pointed me in the right direction.&amp;#160; When you create a new account in Quicken, your opening balance is the first transaction for the account.&amp;#160; In Money, your opening balance is stored in the account and there are no transactions.&amp;#160; This said to me: Quicken cannot calculate a running balance without having that first transaction available.&amp;#160; However, Money can.&amp;#160; What is Money doing differently?&lt;/p&gt;  &lt;p&gt;I don’t know the exact answer to that question, but the solution I came up with was to create a field in the transaction (tx) table that stored the difference, or delta, from the opening balance.&amp;#160; That way, I could take any single transaction or group of transactions, and get the running balance by adding the delta to the opening balance.&amp;#160; I wouldn’t want to store the actual balance in there because if the opening balance was ever changed, I’d have to update EVERY transaction.&lt;/p&gt;  &lt;p&gt;So in simplicity, we have two tables that look like:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; Account(
    ID &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;IDENTITY&lt;/span&gt;(1,1) &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    Name nvarchar(50) &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    OpeningBalance money &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;
) &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt;

&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; AccountTX(
    AccountID &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    TXAmount money &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    AccountDelta money &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    TXID uniqueidentifier &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,
    TXDate datetime &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;
) &lt;span class="kwrd"&gt;ON&lt;/span&gt; PRIMARY&lt;/pre&gt;

&lt;p&gt;And of course the tables have appropriate defaults.&amp;#160; A simple query with populated tables would be&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;select&lt;/span&gt; a.name,tx.txid,tx.txdate,tx.txamount,
    a.openingbalance+tx.accountdelta RunningBalance
&lt;span class="kwrd"&gt;from&lt;/span&gt; accounttx tx
&lt;span class="kwrd"&gt;join&lt;/span&gt; account a &lt;span class="kwrd"&gt;on&lt;/span&gt; a.id=tx.accountid
&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; tx.txdate&lt;/pre&gt;

&lt;p&gt;But we want the database to manage the AccountDelta field itself.&amp;#160; We can’t be expected to make all the updates whenever a user changes the TX amount or moves the date forward or back.&amp;#160; So we’ll handle this with triggers.&lt;/p&gt;

&lt;p&gt;First, the insert.&amp;#160; We’ll assume that a new transaction is always entered at the current date and time (which isn’t realistic, but just play along) and that only one row is inserted at a time.&amp;#160; The trigger would be:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TRIGGER&lt;/span&gt; dbo.Add_AccountTX
&lt;span class="kwrd"&gt;ON&lt;/span&gt;  dbo.AccountTX
INSTEAD &lt;span class="kwrd"&gt;OF&lt;/span&gt; INSERT
&lt;span class="kwrd"&gt;AS&lt;/span&gt; 
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;
    &lt;span class="kwrd"&gt;SET&lt;/span&gt; NOCOUNT &lt;span class="kwrd"&gt;ON&lt;/span&gt;

    &lt;span class="kwrd"&gt;declare&lt;/span&gt; @LastDelta &lt;span class="kwrd"&gt;as&lt;/span&gt; money

    &lt;span class="rem"&gt;-- Get the previous delta from the last transaction    &lt;/span&gt;
    &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;top&lt;/span&gt; 1 @LastDelta=AccountDelta
    &lt;span class="kwrd"&gt;from&lt;/span&gt; AccountTX
    &lt;span class="kwrd"&gt;where&lt;/span&gt; TXDate&amp;lt;getdate()
    &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; TXDate &lt;span class="kwrd"&gt;desc&lt;/span&gt;

    &lt;span class="rem"&gt;-- add the new row with the adjusted delta&lt;/span&gt;
    insert AccountTX(AccountID,TXAmount,AccountDelta)
    &lt;span class="kwrd"&gt;select&lt;/span&gt; AccountID,TXAmount,isnull(@LastDelta,0)+TXAmount AccountDelta
    &lt;span class="kwrd"&gt;from&lt;/span&gt; inserted

END&lt;/pre&gt;

&lt;p&gt;We’re using an INSTEAD OF trigger so we can completely control the insert.&amp;#160; And it’s pretty simple - we get the last delta and add or TX to it when we insert the row.&amp;#160; The DELETE trigger is pretty easy as well - we just deduct the TX amount from any future transactions.&lt;/p&gt;

&lt;p&gt;However, when updating, the user could be changing the TX amount, which affects all future deltas, or they could change the TX date, which will change the deltas from the earlier of the old TX date or new TX date.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;TRIGGER&lt;/span&gt; [dbo].[Update_AccountTX]
&lt;span class="kwrd"&gt;ON&lt;/span&gt;  [dbo].[AccountTX]
&lt;span class="kwrd"&gt;AFTER&lt;/span&gt; &lt;span class="kwrd"&gt;UPDATE&lt;/span&gt;
&lt;span class="kwrd"&gt;AS&lt;/span&gt; 
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;
    &lt;span class="kwrd"&gt;SET&lt;/span&gt; NOCOUNT &lt;span class="kwrd"&gt;ON&lt;/span&gt;
    
    &lt;span class="kwrd"&gt;if&lt;/span&gt; &lt;span class="kwrd"&gt;update&lt;/span&gt;(TXDate)
        &lt;span class="kwrd"&gt;begin&lt;/span&gt;
        &lt;span class="kwrd"&gt;declare&lt;/span&gt; @txAmount money,@txDate datetime,@TXID uniqueidentifier,@LastDelta money
        
        &lt;span class="kwrd"&gt;declare&lt;/span&gt; priorUpdates &lt;span class="kwrd"&gt;cursor&lt;/span&gt; &lt;span class="kwrd"&gt;for&lt;/span&gt;
        &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;old&lt;/span&gt;.TXAmount,&lt;span class="kwrd"&gt;old&lt;/span&gt;.TXDate
        &lt;span class="kwrd"&gt;from&lt;/span&gt; inserted &lt;span class="kwrd"&gt;new&lt;/span&gt;
        &lt;span class="kwrd"&gt;join&lt;/span&gt; deleted &lt;span class="kwrd"&gt;old&lt;/span&gt; &lt;span class="kwrd"&gt;on&lt;/span&gt; &lt;span class="kwrd"&gt;old&lt;/span&gt;.txid=&lt;span class="kwrd"&gt;new&lt;/span&gt;.txid
        &lt;span class="kwrd"&gt;where&lt;/span&gt; &lt;span class="kwrd"&gt;old&lt;/span&gt;.txdate&amp;lt;&lt;span class="kwrd"&gt;new&lt;/span&gt;.txdate
        &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;.TXDate &lt;span class="kwrd"&gt;asc&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;open&lt;/span&gt; priorUpdates
        &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; priorUpdates &lt;span class="kwrd"&gt;into&lt;/span&gt; @txAmount,@txDate
        &lt;span class="kwrd"&gt;while&lt;/span&gt; @@fetch_status=0
            &lt;span class="kwrd"&gt;begin&lt;/span&gt;
            
            &lt;span class="rem"&gt;-- Update future TX to reflect removal of current TX&lt;/span&gt;
            &lt;span class="kwrd"&gt;update&lt;/span&gt; AccountTX &lt;span class="kwrd"&gt;set&lt;/span&gt; AccountDelta=AccountDelta-@txAmount
            &lt;span class="kwrd"&gt;where&lt;/span&gt; TXDate&amp;gt;=@txDate
            
            &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; priorUpdates &lt;span class="kwrd"&gt;into&lt;/span&gt; @txAmount,@txDate
            &lt;span class="kwrd"&gt;end&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;close&lt;/span&gt; priorUpdates
        &lt;span class="kwrd"&gt;deallocate&lt;/span&gt; priorUpdates

        &lt;span class="kwrd"&gt;declare&lt;/span&gt; updates &lt;span class="kwrd"&gt;cursor&lt;/span&gt; &lt;span class="kwrd"&gt;for&lt;/span&gt;
        &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;.TXAmount,&lt;span class="kwrd"&gt;new&lt;/span&gt;.TXDate,&lt;span class="kwrd"&gt;new&lt;/span&gt;.TXID
        &lt;span class="kwrd"&gt;from&lt;/span&gt; inserted &lt;span class="kwrd"&gt;new&lt;/span&gt;
        &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;.TXDate &lt;span class="kwrd"&gt;asc&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;open&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; updates &lt;span class="kwrd"&gt;into&lt;/span&gt; @txAmount,@txDate,@TXID
        &lt;span class="kwrd"&gt;while&lt;/span&gt; @@fetch_status=0
            &lt;span class="kwrd"&gt;begin&lt;/span&gt;
            &lt;span class="rem"&gt;-- get the previous delta&lt;/span&gt;
            &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;top&lt;/span&gt; 1 @LastDelta=AccountDelta
            &lt;span class="kwrd"&gt;from&lt;/span&gt; AccountTX
            &lt;span class="kwrd"&gt;where&lt;/span&gt; TXDate&amp;lt;@txDate
            &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; TXDate &lt;span class="kwrd"&gt;desc&lt;/span&gt;
                        
            &lt;span class="rem"&gt;-- Update the delta for the row moved&lt;/span&gt;
            &lt;span class="kwrd"&gt;update&lt;/span&gt; AccountTX &lt;span class="kwrd"&gt;set&lt;/span&gt; AccountDelta=isnull(@LastDelta,0)+@txAmount
            &lt;span class="kwrd"&gt;where&lt;/span&gt; TXID=@TXID
            
            &lt;span class="rem"&gt;-- Update all future transactions&lt;/span&gt;
            &lt;span class="kwrd"&gt;update&lt;/span&gt; AccountTX &lt;span class="kwrd"&gt;set&lt;/span&gt; AccountDelta=AccountDelta+@txAmount
            &lt;span class="kwrd"&gt;where&lt;/span&gt; TXDate&amp;gt;@txDate
            
            &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; updates &lt;span class="kwrd"&gt;into&lt;/span&gt; @txAmount,@txDate,@TXID
            &lt;span class="kwrd"&gt;end&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;close&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;deallocate&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;end&lt;/span&gt;    
    
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; &lt;span class="kwrd"&gt;update&lt;/span&gt;(TXAmount) 
        &lt;span class="kwrd"&gt;begin&lt;/span&gt;
        &lt;span class="kwrd"&gt;declare&lt;/span&gt; @diff money,@minDate datetime
        &lt;span class="kwrd"&gt;declare&lt;/span&gt; updates &lt;span class="kwrd"&gt;cursor&lt;/span&gt; &lt;span class="kwrd"&gt;for&lt;/span&gt;
        &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;.TXAmount-&lt;span class="kwrd"&gt;old&lt;/span&gt;.TXAmount Diff,&lt;span class="kwrd"&gt;new&lt;/span&gt;.TXDate
        &lt;span class="kwrd"&gt;from&lt;/span&gt; inserted &lt;span class="kwrd"&gt;new&lt;/span&gt;
        &lt;span class="kwrd"&gt;join&lt;/span&gt; deleted &lt;span class="kwrd"&gt;old&lt;/span&gt; &lt;span class="kwrd"&gt;on&lt;/span&gt; &lt;span class="kwrd"&gt;old&lt;/span&gt;.txID=&lt;span class="kwrd"&gt;new&lt;/span&gt;.tXID
        &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;.TXDate &lt;span class="kwrd"&gt;asc&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;open&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; updates &lt;span class="kwrd"&gt;into&lt;/span&gt; @diff,@minDate
        &lt;span class="kwrd"&gt;while&lt;/span&gt; @@fetch_status=0
            &lt;span class="kwrd"&gt;begin&lt;/span&gt;
            &lt;span class="rem"&gt;-- Update all future transaction with the difference&lt;/span&gt;
            &lt;span class="kwrd"&gt;update&lt;/span&gt; AccountTX &lt;span class="kwrd"&gt;set&lt;/span&gt; AccountDelta=AccountDelta+@diff
            &lt;span class="kwrd"&gt;where&lt;/span&gt; TXDate&amp;gt;=@minDate
            
            &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; updates &lt;span class="kwrd"&gt;into&lt;/span&gt; @diff,@minDate    
            &lt;span class="kwrd"&gt;end&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;close&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;deallocate&lt;/span&gt; updates
        &lt;span class="kwrd"&gt;end&lt;/span&gt;
&lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Yeah, it’s bulky.&amp;#160; There’s two sections depending on whether the amount changed or the date changed.&amp;#160; The date is difficult because you have to handle TX’s moving forward and backward, and it’s essentially doing an insert and a delete.&amp;#160; The change to the amount is simple, it’s only twist is having to determine how much the difference is to apply to future deltas.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;But, the point of the exercise was to see if I could do it at all, and I feel comfortable with what I’ve got.&amp;#160; The bulk of the code will be in display of the transactions and the investment logic.&amp;#160; If Money’s UI isn’t already written in WPF, then that would be an excellent fit for the design.&amp;#160; We’ll go slowly on this.&amp;#160; I need to make sure that I have some other concepts worked out as well.&lt;/p&gt;

&lt;p&gt;But that will be discussed in the coming year.&amp;#160; Good riddance, 2009.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=286" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>Zune HD Video: Free, but not for the faint of heart</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/10/05/zune-hd-video-free-but-not-for-the-faint-of-heart.aspx</link><pubDate>Mon, 05 Oct 2009 14:18:04 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:284</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=284</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/10/05/zune-hd-video-free-but-not-for-the-faint-of-heart.aspx#comments</comments><description>&lt;p&gt;I recently got myself a Zune HD.&amp;#160; I do like it a lot.&amp;#160; But now my video files just don’t have the quality to impress anyone when I want to show it off.&amp;#160; So I decided to re-rip some of my videos in a higher definition.&amp;#160; I soon remembered how much I hate video conversion.&lt;/p&gt;  &lt;p&gt;My goal was to get the highest quality file onto the Zune HD without having the Zune software transcode it and to do it using freeware tools.&amp;#160; Whenever you choose to go the freeware route, you’re going to be sacrificing convenience.&lt;/p&gt;  &lt;p&gt;The big hammer in my toolbox is the free Windows Media Encoder (WME).&amp;#160; This will encode to WMV, which is a format the Zune loves to eat.&amp;#160; So everything I’m doing is revolving around this tool.&amp;#160; However, now I need a bunch of additional tools to work around its shortcomings.&lt;/p&gt;  &lt;p&gt;WME will only work with a single file at a time, so DVDs with multiple VOB files can’t be processed directly.&amp;#160; So, I used DVDShrink to rip the main feature from a DVD to a single VOB file (this is set in the options).&amp;#160; At the same time, I used DVD43 to remove the encryption.&amp;#160; DVD43 only works under 32-bit systems, so I run DVD43 and DVDShrink in a Windows XP virtual machine hosted with Sun VirtualBox.&lt;/p&gt;  &lt;p&gt;So far, we have 4 programs involved.&amp;#160; The VOB is now ripped and put into WME.&amp;#160; Now is an excellent time to discover that WME doesn’t read AC3 audio from VOBs.&amp;#160; Now we need a program to demux the audio into its own file and let WME mux them back together.&amp;#160; This can be done pretty easily with BeSweet, but you also need to download the VOBInput.dll additional file.&lt;/p&gt;  &lt;p&gt;Now 5 programs.&amp;#160; Now WME can read the video from the VOB, the audio from the WAV and put them together.&amp;#160; But on the very first DVD I tried – Talking Heads, Stop Making Sense – the encode would stop after about 40 minutes.&amp;#160; Looking at the details a little closer, the VOB was reported to be 40 minutes long, but the WAV was 1:28 long.&amp;#160; When playing the VOB, the time would reset to zero after the 40 minute mark.&amp;#160; This, I’ve learned, is a timecode break.&amp;#160; Now we need a tool to fix this.&lt;/p&gt;  &lt;p&gt;The timecode break can be fixed using a tool called StreamClip.&amp;#160; And it requires that Quicktime Alternative 1.81 be installed.&amp;#160; These are going on the virtual machine so as not to pollute my main system.&amp;#160; Unfortunately, StreamClip seems to be designed for Apple users (the cancel button is on the left of the windows), so all the audio export features are incompatible with WME, so BeSweet has to be kept.&lt;/p&gt;  &lt;p&gt;So in summary, this is what I needed to take a DVD and put it on the Zune HD, in order of execution:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.virtualbox.org"&gt;Sun VirtualBox&lt;/a&gt; – Host for a 32-bit Windows install&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.dvd43.com"&gt;DVD43&lt;/a&gt; – Decrypts DVDs.&amp;#160; Only runs in 32-bit.&amp;#160; Run in virtual machine.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.filehippo.com/download_dvdshrink"&gt;DVDShrink&lt;/a&gt; – Rips DVD to single VOB file for processing.&amp;#160; Run in virtual machine&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.oldapps.com/quicktime_alt.php?old_quicktime_alt=48"&gt;Quicktime Alternative&lt;/a&gt; – Needed for StreamClip. Run in virtual machine&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.squared5.com"&gt;StreamClip&lt;/a&gt; – Fixes timecode breaks in VOB file (not always needed). Run in virtual machine&lt;/li&gt;    &lt;li&gt;&lt;a href="http://besweet.notrace.dk"&gt;BeSweet&lt;/a&gt; – Extracts audio from VOB to WAV&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/windows/windowsmedia/forpros/encoder/default.mspx"&gt;Windows Media Encoder&lt;/a&gt; – Creates the WMV file from the VOB and WAV files.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That’s a lot of programs and a lot of work, but hey, it’s free!&lt;/p&gt;  &lt;p&gt;Once I have a workable routine, I’ll try to post something on it.&amp;#160; The BeSweet and WME steps aren’t just a simple point-and-click procedure.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=284" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ramblings/default.aspx">Ramblings</category></item><item><title>A Toolbar of Your Favorite Menu Items?  Interesting…</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/09/02/a-toolbar-of-your-favorite-menu-items-interesting.aspx</link><pubDate>Wed, 02 Sep 2009 01:32:04 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:283</guid><dc:creator>anachostic</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=283</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/09/02/a-toolbar-of-your-favorite-menu-items-interesting.aspx#comments</comments><description>&lt;p&gt;Remember that little idea that Office had a while ago that would hide infrequently-used menu items?&amp;#160; Wasn’t that a great idea?&amp;#160; For me, it was the very first thing I turned off after installing Office.&amp;#160; But I do understand what they were going after.&amp;#160; When applications do so much, every user is probably just using a subset of the whole application’s features.&lt;/p&gt;  &lt;p&gt;The application that I’m writing is kind of getting like that.&amp;#160; A few versions ago, I created a toolbar on the side that was planned to be context-sensitive, so it would show actions based on what data was shown and available - kind of how Microsoft is now doing with the task pane.&amp;#160; Eventually, I may create or convert the toolbar to a task pane.&amp;#160; But as the application was growing, I had the same thought the Office designers had: each user probably only cares about 5 or 6 menu items at a time and those items should be as readily available as possible.&amp;#160; So instead of making personalized menus, I decided to create a Favorites toolbar.&amp;#160; This is similar to Microsoft programs where you can add toolbars and put menu items on them.&lt;/p&gt;  &lt;p&gt;Because the application is in flux and because I am lazy, I didn’t want to go through the effort of creating a “Customize Toolbar” dialog.&amp;#160; I also didn’t want to have an extra dialog for “Add To Favorites”.&amp;#160; So what I did was allow menu items to be dragged onto the toolbar.&amp;#160; The proof-of-concept started as most do, just to see how it would work.&amp;#160; I got it going in under 150 lines of code, even less considering whitespace and definitions and all.&amp;#160; &lt;/p&gt;  &lt;p&gt;To quickly summarize the technique, I started by putting a toolbar container on the form, adding a toolstrip to hold the favorites, and adding a menu to hold the draggable items.&lt;/p&gt;  &lt;p&gt;Then I added the code to allow the dragging of the menu items:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Menu_MouseMove(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; MouseEventArgs) _
        &lt;span class="kwrd"&gt;Handles&lt;/span&gt; mnuFirst.MouseMove, mnuSecond.MouseMove, mnuThird.MouseMove, mnuFourth.MouseMove, _
        mnu2ndLevel1.MouseMove, mnu2ndLevel2.MouseMove, mnu2ndLevel3.MouseMove

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; item &lt;span class="kwrd"&gt;As&lt;/span&gt; ToolStripMenuItem

        &lt;span class="kwrd"&gt;If&lt;/span&gt; e.Button = Windows.Forms.MouseButtons.Left &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            item = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(sender, ToolStripMenuItem)
            item.DoDragDrop(item, DragDropEffects.Copy)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;Then the code to drop the items (the toolstrip needs to have AllowDrop set to &lt;strong&gt;True&lt;/strong&gt;):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; toolFavorites_DragEnter(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; DragEventArgs) _
        &lt;span class="kwrd"&gt;Handles&lt;/span&gt; toolFavorites.DragEnter

        &lt;span class="kwrd"&gt;If&lt;/span&gt; e.AllowedEffect = DragDropEffects.Copy &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; e.Data.GetDataPresent(&lt;span class="kwrd"&gt;GetType&lt;/span&gt;(ToolStripItem)) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            e.Effect = DragDropEffects.Copy
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; toolFavorites_DragDrop(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; DragEventArgs) _
        &lt;span class="kwrd"&gt;Handles&lt;/span&gt; toolFavorites.DragDrop

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; droppedItem &lt;span class="kwrd"&gt;As&lt;/span&gt; ToolStripItem

        droppedItem = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(e.Data.GetData(&lt;span class="kwrd"&gt;GetType&lt;/span&gt;(ToolStripItem)), ToolStripItem)
        AddToFavorites(droppedItem)

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; AddToFavorites(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; item &lt;span class="kwrd"&gt;As&lt;/span&gt; ToolStripItem)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; newItem &lt;span class="kwrd"&gt;As&lt;/span&gt; ToolStripButton

        newItem = &lt;span class="kwrd"&gt;New&lt;/span&gt; ToolStripButton(item.Text, item.Image)
        newItem.Tag = item
        &lt;span class="kwrd"&gt;AddHandler&lt;/span&gt; newItem.MouseDown, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; FavoritesContext
        &lt;span class="kwrd"&gt;AddHandler&lt;/span&gt; newItem.Click, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; FavoritesClick
        &lt;span class="kwrd"&gt;AddHandler&lt;/span&gt; item.EnabledChanged, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; OnMenuEnabledChanged

        toolFavorites.Items.Add(newItem)

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;Then the code to route the click of the favorites to the real menu item&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FavoritesClick(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; EventArgs)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; item &lt;span class="kwrd"&gt;As&lt;/span&gt; ToolStripItem

        item = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(&lt;span class="kwrd"&gt;CType&lt;/span&gt;(s, ToolStripItem).Tag, ToolStripMenuItem)
        item.PerformClick()

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;That was really it.&amp;#160; Of course, then I had to persist the favorites in My.Settings and provide a way of removing the favorite menu item, resulting in the above-referenced AddHandler statement for FavoritesContext and a couple other methods for running through the menu items on the form load and close.&amp;#160; Then we need to disable the favorite button when the linked menu item is disabled, leading to the AddHandler for OnMenuEnabledChanged.&amp;#160; It just keeps growing.&lt;/p&gt;

&lt;p&gt;I wanted to keep the post short, so if you’re interesting in these other pieces, I put a ZIP of the POC source at &lt;a href="http://www.700cb.net/Downloads/DragMenus.zip"&gt;http://www.700cb.net/Downloads/DragMenus.zip.&lt;/a&gt;&amp;#160; That something I usually don’t do.&amp;#160; Interesting…&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=283" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>Opportunistic Hackers – It’s About Time</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/08/27/opportunistic-hackers-it-s-about-time.aspx</link><pubDate>Thu, 27 Aug 2009 02:09:42 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:282</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=282</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/08/27/opportunistic-hackers-it-s-about-time.aspx#comments</comments><description>&lt;p&gt;A recent event that made some blog headlines got me thinking about security and stuff.&amp;#160; I’ve been thinking about it for a couple nights and every time I remember it, I am too tired to actually write anything.&amp;#160; The event was some hacking and defamation of some Facebook sites, probably Christian users.&amp;#160; I was online the night that the passwords got hacked and I remember making a post elsewhere warning people to change their passwords.&amp;#160; Almost 6 months later, the attackers organized and used that information.&lt;/p&gt;  &lt;p&gt;From reading posts on other sites, there’s a few things wrong with the security model in place.&amp;#160; The flaw used to be weak passwords (and still is, I’m sure).&amp;#160; Another flaw was using the same password for multiple sites.&amp;#160; The current flaw is the security question to reset a password, where the answer to that question can be found online, possibly posted by the victim.&amp;#160; The attacker gains access to the victim’s email account, but can’t get to other accounts (Facebook, Paypal, banking, etc), so they answer the security questions to reset the password and have the new password sent to the email account they have access to.&lt;/p&gt;  &lt;p&gt;There’s two things I propose to squelch this.&amp;#160; First, understand that hacking is best done in a hurry.&amp;#160; The longer you mess around in someone’s account, the more likely it is you will get caught.&amp;#160; So, delay the delivery of the new password for 24-48 hours.&amp;#160; Ideally, this would be user-defined setting in a member profile.&amp;#160; This is better understood when you know the other half of my security proposal.&amp;#160; Sure, if someone forgets their password, they will have to wait 24-48 hours to get their new password.&amp;#160; That is an inconvenience in the name of security, but resetting a password is a last-ditch effort.&amp;#160; If someone logs in frequently, they know their password.&amp;#160; The most common case would be someone who hasn’t logged in for many months.&amp;#160; If they haven’t been active on the site for months, what’s an extra 24 hours?&lt;/p&gt;  &lt;p&gt;Ok, the second part of the improvement, probably the more important part: the password reset request is queued.&amp;#160; You’d think that when a user hits “forgot password” and answers the security question, the password is reset and the email is generated.&amp;#160; Well, now the email is delayed by a day or two.&amp;#160; What happens is the user successfully logs in during that window of time?&amp;#160; Yes, they do know their password; there is no need to reset it.&amp;#160; The request can be cancelled and the user notified that a reset request was attempted.&amp;#160; If the user thought their password was compromised, they would not use the Forgot Password/Reset Password function, they would change their password in the edit profile section after logging in.&lt;/p&gt;  &lt;p&gt;Think of it this way.&amp;#160; You’re talking to a (soon to be untrustworthy) colleague.&amp;#160; In the casual conversation, you mention what seems like innocent information about yourself, then you excuse yourself, saying that there’s a package at UPS you need to pick up.&amp;#160; The colleague rushes to the UPS store and says “I’m John Smith from ABC Company.&amp;#160; You have a package waiting for me?”&amp;#160; If the clerk is bright, he’ll ask for ID.&amp;#160; In lieu of ID, the imposter may or may not successfully convince the clerk he is you using the information gleaned from a casual conversation (or maybe from online stalking).&lt;/p&gt;  &lt;p&gt;What I am suggesting is that because positive proof couldn’t be made with an ID (your password), the clerk says “We’ll have your package ready at the close of day.&amp;#160; Stop back then to pick it up.”&amp;#160; Now if you show up half an hour later to pick up the package and show your ID (your password), the interception attempt was foiled and maybe you can catch the imposter when he comes back in later.&lt;/p&gt;  &lt;p&gt;This is why I suggest having the reset delay be user-configurable.&amp;#160; It’s a balance of convenience vs. security (not unlike “remember me on this computer”).&amp;#160; If a person knows they log in to a site at least once a day, 12 hours might be sufficient.&amp;#160; If you only use the site once a month, maybe a 3 day delay with notifications emailed at random times telling you how much time is left.&amp;#160; A hacker would have to monitor your email constantly and random times to intercept all the notifications.&lt;/p&gt;  &lt;p&gt;This idea came about from an old article I read about how you could get away with less restrictive password policies if you implemented an expiring lockout after X failed login attempts.&amp;#160; The theory was, if an attacker is using a script or other random generating tool to brute force a login, stalling the login attempts for 15 minutes after every 5 failed logins makes the attack unrealistic because the Change Password policy would require the user to change the password before the brute force attack could finish all the possibilities.&amp;#160; Then they’d have to start over.&amp;#160; What a waste of time.&lt;/p&gt;  &lt;p&gt;These are just ideas, but as people start keeping and sharing more personal information online, security based on that personal information is less secure, duh.&amp;#160; So by making the bad guys wait, the good guys have a chance at taking action.&amp;#160; That’s probably why bank robbers run out the door instead of scanning the marketing brochures.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=282" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Observations/default.aspx">Observations</category></item><item><title>Falling Behind the Times</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/08/09/falling-behind-the-times.aspx</link><pubDate>Sun, 09 Aug 2009 21:26:56 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:281</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=281</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/08/09/falling-behind-the-times.aspx#comments</comments><description>&lt;p&gt;The other day I was writing some code and I got an error message.&amp;#160; It happened to be one of those cases where it should have worked.&amp;#160; You know when good code it written it just happens to work like you expect it to.&amp;#160; The general idea was:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FillCombos()
        Dim dict As New Dictionary(Of String, String)&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;With&lt;/span&gt; dict
            .Add(&lt;span class="str"&gt;&amp;quot;Steve&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Steve Harris&amp;quot;&lt;/span&gt;)
            .Add(&lt;span class="str"&gt;&amp;quot;Bill&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Bill Murray&amp;quot;&lt;/span&gt;)
            .Add(&lt;span class="str"&gt;&amp;quot;Dave&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Dave&amp;#39;s not here&amp;quot;&lt;/span&gt;)
            .Add(&lt;span class="str"&gt;&amp;quot;Jack&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot; (Captain) Jack Sparrow&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;With&lt;/span&gt;

        ComboBox1.DataSource = dict.Keys
        ComboBox2.DataSource = dict.Values

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;Seems pretty logical.&amp;#160; The Keys property of a dictionary is a collection and so is the Values.&amp;#160; A collection is just a list of things.&amp;#160; They should be bindable, right?&amp;#160; Well, no.&amp;#160; The error you get is: “Complex DataBinding accepts as a data source either an IList or an IListSource.”&amp;#160; And after poking around, it’s right.&amp;#160; The collections do not implement those interfaces.&lt;/p&gt;

&lt;p&gt;So that was going to be a blog topic about how and why those collections couldn’t be databound, but when I tried it on my other computer, I noticed that I had extra methods on those collections, ToArray being one of them.&amp;#160; so I used ToArray and the databinding worked.&amp;#160; As it turns out, the ToArray was added from System.Linq.Enumerable, which comes along with .NET 3.0.&amp;#160; I switched the project to .NET 2.0 and the ToArray function disappeared.&lt;/p&gt;

&lt;p&gt;So now, I’m blogging more about the blunt realization that I’m officially missing out on additional functionality that would have simplified my code.&amp;#160; Well, as complicated as this solution makes it:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;ComboBox1.DataSource = &lt;span class="kwrd"&gt;New&lt;/span&gt; Generic.List(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(dict.Keys)
ComboBox2.DataSource = &lt;span class="kwrd"&gt;New&lt;/span&gt; Generic.List(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(dict.Values)&lt;/pre&gt;

&lt;p&gt;So, with the release of Windows 7, I do plan on installing VS 2008 at work and driving ahead with 64-bit development under .NET 3.5.&amp;#160; Well, eventually.&amp;#160; There’s still some Win2k workstations out there…&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=281" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Observations/default.aspx">Observations</category></item><item><title>Dating Advice</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/07/19/dating-advice.aspx</link><pubDate>Sun, 19 Jul 2009 15:05:19 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:280</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=280</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/07/19/dating-advice.aspx#comments</comments><description>&lt;p&gt;No, I certainly can’t help you get dates or have successful dates.&amp;#160; But I can offer a couple of functions that might help you work with dates in your code.&amp;#160; I suck at dates (all types).&amp;#160; Every time I want to calculate dates, I need to print a calendar from Outlook and count the days.&amp;#160; It’s pretty ironic that one of my previous projects was all about schedules.&amp;#160; And one of my current projects deals with delivery schedules as well.&amp;#160; So I can’t escape it.&lt;/p&gt;  &lt;p&gt;I always would get frustrated because every month was different.&amp;#160; Every month started on a different day and had a different number of days.&amp;#160; It felt impossible to get all the different combinations.&amp;#160; But recently, I had a moment of clarity and realized some basic facts about a month.&amp;#160; Things like:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;No month has less than 28 days&lt;/li&gt;    &lt;li&gt;This guarantees every month will have 4 weeks&lt;/li&gt;    &lt;li&gt;This guarantees there are no less than 4 and no more than 5 of every weekday in a month &lt;/li&gt;    &lt;li&gt;The only weekdays that will have 5 occurrences will be the days in excess of 28.&amp;#160; These days can be accounted for at the beginning or end of the month – it doesn’t matter.&lt;/li&gt;    &lt;li&gt;By extension, there are a minimum of 20 workdays in a month (Mon-Fri)&lt;/li&gt;    &lt;li&gt;And, any additional workdays will be those in excess of 28 that are between Monday and Friday&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Earlier attempts to figure out the number of workdays in a month resulted in a brute force loop that would run through every day from 1 to 31 and if the DayOfWeek was Mon-Fri, increment a counter.&amp;#160; Now, with these new guidelines, I can start at 20 and only deal with 0-3 excess days.&amp;#160; Like with this function:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; WorkdaysInMonth(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; d &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; daysInMonth &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; extraWeekDays &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;

    daysInMonth = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(d.Year, d.Month, 1).AddMonths(1).AddDays(-1).Day

    &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; daysInMonth - 28
        &lt;span class="kwrd"&gt;Select&lt;/span&gt; &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(d.Year, d.Month, i).DayOfWeek
            &lt;span class="kwrd"&gt;Case&lt;/span&gt; DayOfWeek.Monday, DayOfWeek.Tuesday, _
                DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday

                extraWeekDays += 1

        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Select&lt;/span&gt;

    &lt;span class="kwrd"&gt;Next&lt;/span&gt;

    &lt;span class="kwrd"&gt;Return&lt;/span&gt; 20 + extraWeekDays

&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Using the other rules for weekdays, we know we only need to deal with the exceptions, to find out whether there are 5 weekdays in a month:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; NumberOfWeekdaysInMonth(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; weekday &lt;span class="kwrd"&gt;As&lt;/span&gt; DayOfWeek, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; referenceDate &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; firstDay &lt;span class="kwrd"&gt;As&lt;/span&gt; DayOfWeek
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; lastDay &lt;span class="kwrd"&gt;As&lt;/span&gt; DayOfWeek

    firstDay = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(referenceDate.Year, referenceDate.Month, 1).DayOfWeek
    lastDay = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(referenceDate.Year, referenceDate.Month, 1).AddMonths(1).AddDays(-1).DayOfWeek

    &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(referenceDate.Year, referenceDate.Month, 1).AddMonths(1).AddDays(-1).Day = 28 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; 4

    &lt;span class="kwrd"&gt;ElseIf&lt;/span&gt; lastDay &amp;gt;= firstDay &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;gt;= firstDay &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;lt;= lastDay &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; 5

    &lt;span class="kwrd"&gt;ElseIf&lt;/span&gt; lastDay &amp;lt; firstDay &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;gt;= firstDay - 7 &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;lt;= lastDay &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; 5

    &lt;span class="kwrd"&gt;ElseIf&lt;/span&gt; lastDay &amp;lt; firstDay &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;gt;= firstDay &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; weekday &amp;lt;= lastDay + 7 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; 5

    &lt;span class="kwrd"&gt;Else&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; 4

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;p&gt;That one got a bit hairy because is the extra days started at the end of the week with a high DayOfWeek value, and ended early in the week with a low DayOfWeek value, we had to compensate at each end.&amp;#160; That’s the reasons for all the different IF conditions.&amp;#160; There’s also a specific condition for February’s 28 days.&lt;/p&gt;

&lt;p&gt;Finally, a function to determine the first, second, third, fourth, or fifth weekday in a month.&amp;#160; Useful when calculating holidays like Labor Day and Thanksgiving.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; NthDayOfMonth(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; index &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; weekDay &lt;span class="kwrd"&gt;As&lt;/span&gt; DayOfWeek, _
    &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; referenceDate &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;

    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; firstDay &lt;span class="kwrd"&gt;As&lt;/span&gt; DayOfWeek
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; dayOfMonth &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;

    firstDay = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(referenceDate.Year, referenceDate.Month, 1).DayOfWeek
    dayOfMonth = (7 * (index - 1)) + _
        &lt;span class="kwrd"&gt;CInt&lt;/span&gt;(IIf(firstDay &amp;gt; weekDay, 7 + weekDay - firstDay, weekDay - firstDay))

    &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(referenceDate.Year, referenceDate.Month, dayOfMonth + 1)

&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=280" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>This’ll Be Easy</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/07/03/this-ll-be-easy.aspx</link><pubDate>Fri, 03 Jul 2009 21:23:50 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:279</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=279</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/07/03/this-ll-be-easy.aspx#comments</comments><description>&lt;p&gt;So many great adventures start with this line.&amp;#160; I am just wrapping up my own.&amp;#160; The task was simple:&amp;#160; Upgrade the hard drive in my laptop.&amp;#160; I was going from 80GB to 320GB.&amp;#160; What’s so hard about that?&amp;#160; You use Ghost, you have it resize the partition to the max and go.&lt;/p&gt;  &lt;h3&gt;The First Attempt (5 hours, no success)&lt;/h3&gt;  &lt;p&gt;I borrowed a SATA “toaster” – a USB device that has a SATA dock in it and hooked it up to the laptop.&amp;#160; I booted a CD to Ghost.&amp;#160; The software recognized the internal drive and the external USB drive.&amp;#160; I took all the defaults.&amp;#160; When it started, my hopes sank as I saw the time remaining climb and climb.&amp;#160; Ok, so maybe copying 80GB over USB isn’t that great of an idea – I’ll accept blame for that.&amp;#160; That would’ve been tolerable except that the copy failed with a sector write error with 15 minutes to go.&amp;#160; Ok, back to work and we’ll pick this up later.&lt;/p&gt;  &lt;h3&gt;Attempts 2-5 (or more.) &lt;/h3&gt;  &lt;p&gt;This time I was a little smarter.&amp;#160; I pulled the internal drive from the laptop and used the SATA connectors in my desktop to copy between the two drives.&amp;#160; This completed the copy in only 40 minutes.&amp;#160; However, after installing the new drive in the laptop, the copy would never boot.&amp;#160; I tried each of the different options in Ghost, eventually giving up that I’d be able to extend the partition.&amp;#160; None of them worked.&amp;#160; The probable cause?&amp;#160; It’s an HP laptop and the drive has a stupid recovery partition.&amp;#160; Not only does it have the 5GB recovery partition, but also a tiny 2MB unknown partition that is ID 0, to start first.&amp;#160; When doing a partition copy, Ghost never copied it.&amp;#160; When doing a full sector copy, which should include it, the transition from the custom boot sector to the main partition never happened.&lt;/p&gt;  &lt;h3&gt;Stepping Back and Research&lt;/h3&gt;  &lt;p&gt;At this point, I’ve powered my desktop on and off more times that I have in over a year.&amp;#160; I’ve been swapping drives back and forth so I can use my desktop for research and then again use the CD for booting Ghost.&amp;#160; Somewhere along the way, I decided to buy another SATA cable ($20 from Best Buy and I still feel violated by it).&amp;#160; &lt;/p&gt;  &lt;p&gt;I downloaded True Image and Disk Director and decided they wouldn’t do the job before even installing them.&amp;#160; I read up on the latest Ghost and it seems to be just some backup software now.&amp;#160; Then I hit upon Disk Copy from EaseUS.&amp;#160; It’s free and seems to be self-contained in a bootable CD.&amp;#160; A couple more reboots and downloads, including the very impressive ISO Recorder (also freeware) and I was ready to go.&lt;/p&gt;  &lt;h3&gt;The Final Snail (an inside joke)&lt;/h3&gt;  &lt;p&gt;Booting up to Disk Copy, I selected the sector copy option and let it run.&amp;#160; It was a little slower than Ghost – instead of 2.2GB/minute, it was 1.7GB/min.&amp;#160; That added an extra 10 minutes of time.&amp;#160; But it paid off, because the new drive booted!&amp;#160; I’m pleased enough now that I’m not concerned about resizing the original partition.&amp;#160; I’m just going to create a new partition to hold my 60GB databases and other large files.&lt;/p&gt;  &lt;p&gt;So, in summary, the HP recovery partition makes cloning drives impossible using Ghost (version copyright 2003), but using Disk Copy from EaseUS was successful.&amp;#160; EaseUS also has a freeware partition manager, but I didn’t feel like trying it.&lt;/p&gt;  &lt;p&gt;And the funny part about all this is that the laptop is going to be slicked as soon as Windows 7 is available on MSDN.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=279" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ramblings/default.aspx">Ramblings</category></item><item><title>Not Enough Time</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/06/17/not-enough-time.aspx</link><pubDate>Wed, 17 Jun 2009 01:23:28 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:277</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=277</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/06/17/not-enough-time.aspx#comments</comments><description>&lt;p&gt;I had something that I thought was a simple task and got the solution for it, but when I researched it, I didn’t see a whole lot of other people talking about it.&amp;#160; Actually, in my brief searches, I didn’t see anyone talking about it.&amp;#160; So here goes.&lt;/p&gt;  &lt;p&gt;What do you do if you want to add a time to a date?&amp;#160; Most people would say, “Duh.&amp;#160; A date is a time.&amp;#160; That’s why they call it DateTime.”&amp;#160; But say for the sake of argument, you have two variables, one holds a date and one holds a time.&amp;#160; The time portion is irrelevant in your date variable because you always use .ToShortDateString and likewise with the time variable always using .ToShortTimeString.&amp;#160; Now you want them together.&lt;/p&gt;  &lt;p&gt;Take the following block of code:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; baseDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; newDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime

baseDate = DateTime.Now
newDate = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Date&lt;/span&gt;(2012, 12, 20)

&lt;span class="rem"&gt;&amp;#39; Insert here&lt;/span&gt;

MsgBox(baseDate.ToString &amp;amp; &lt;span class="str"&gt;&amp;quot; = &amp;quot;&lt;/span&gt; &amp;amp; newDate.ToString)&lt;/pre&gt;

&lt;p&gt;Which statement placed in “Insert here” will be the most efficient, judging by IL code generated?&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Version 1&lt;/span&gt;
newDate = newDate.AddHours(baseDate.Hour) _
    .AddMinutes(baseDate.Minute) _
    .AddSeconds(baseDate.Second) _
    .AddMilliseconds(baseDate.Millisecond)

&lt;span class="rem"&gt;&amp;#39; Version 2&lt;/span&gt;
newDate = &lt;span class="kwrd"&gt;Date&lt;/span&gt;.Parse(newDate.ToShortDateString _
    &amp;amp; &lt;span class="str"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &amp;amp; baseDate.ToLongTimeString)

&lt;span class="rem"&gt;&amp;#39; Version 3&lt;/span&gt;
newDate = newDate.&lt;span class="kwrd"&gt;Date&lt;/span&gt;.Add(baseDate.Subtract(baseDate.&lt;span class="kwrd"&gt;Date&lt;/span&gt;))&lt;/pre&gt;

&lt;p&gt;You might be surprised like I was, but #2 is the best, unless you need millisecond precision, then #2 is disqualified, making #3 the best.&amp;#160; Probably no surprise, #1 is the worst because every .Add[interval] call creates a new temporary value in IL.&lt;/p&gt;

&lt;p&gt;You might be looking at #1 thinking “Who would do something like that?” When I first had the need to add a date and a time, I considered that route for about a second and thought there has to be a better way.&amp;#160; I settled on using #3, figuring if I added a time with zero days on it (by subtracting out the date portion) it would give me the TimeSpan structure I needed to add to the date portion of my original date.&lt;/p&gt;

&lt;p&gt;TimeSpan is a really nice structure that probably doesn’t get as much exposure as some other .NET elements like StringBuilder.&amp;#160; &lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=277" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Troubleshooting/default.aspx">Troubleshooting</category></item><item><title>OMG, ur doin it wrong.</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/05/23/omg-ur-doin-it-wrong.aspx</link><pubDate>Sat, 23 May 2009 17:54:40 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:274</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=274</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/05/23/omg-ur-doin-it-wrong.aspx#comments</comments><description>&lt;p&gt;You know, when you think of a popular website, run by a pretty big company, you would expect that they would have a pretty good software development team.&amp;#160; If you think of the popularity of a website and how much impact poor code would have to their servers and how much impact a poor user experience would have to their customers, then it’s pretty clear, you need to have good code.&lt;/p&gt;  &lt;p&gt;I don’t usually like to crap all over someone’s coding.&amp;#160; I will criticize and I think I am pretty good about being flexible about differences in coding styles.&amp;#160; But sometimes there is a case that is SO flagrantly bad, it has to be called out.&amp;#160; And the subject in this case is The Weather Channel.&lt;/p&gt;  &lt;p&gt;I recently noticed that the interactive weather map page had changed.&amp;#160; And in this change, it stopped working in my browser of choice: Opera.&amp;#160; The specific problems that caused me to dive into the code (and subsequently begin projectile vomiting) were that it would freeze partway though the page load (hitting stop would display the remainder of the page) and that the map animation would only load the first two images and then freeze.&amp;#160; I never got to the point of troubleshooting them.&lt;/p&gt;  &lt;p&gt;Let’s start with the stats that will knock you on your ass.&amp;#160; This page alone, just the HTML code, not the linked scripts, not the images, is 223k.&amp;#160; It is 5500 lines of code.&amp;#160; Can you fathom that?&amp;#160; An immensely popular web page being an incredible 223 kb in size.&amp;#160; Now can you imagine being the developer creating and maintaining a 5500-line web page?&lt;/p&gt;  &lt;p&gt;So, I saved off the HTML code and loaded it in VS.&amp;#160; There was a slight problem with the Format Document function because of a misformatted tag (go figure).&amp;#160; VS was nice enough to tell me which line the issue was on, so I could fix it.&amp;#160; Awesome.&amp;#160; I spent about 30 minutes reading through the code up until about line 1500.&amp;#160; Then I thought I’d get some more basic stats.&lt;/p&gt;  &lt;p&gt;The inline JavaScript consumes over 3600 lines of the source.&amp;#160; There were cases where the inline scripts were 520 lines, 423 lines, 400 lines, 300 lines and so on down.&amp;#160; Do you feel ill yet, I sure do.&amp;#160; The inline style sheets took up another 260 lines.&lt;/p&gt;  &lt;p&gt;Next, the comments left in the code indicate there’s something not so top-notch going on.&amp;#160; A couple noteworthy samples: “Daniel Test for in the morning”, “Debugging Comments” “Combined html for optimization.” (oh, the irony) and the best one, “ADDED THIS CLOSING DIV BECAUSE IT WAS IN ORIGINAL CODE, CAN&amp;#39;T FIND MATCHING OPENING DIV”&amp;#160; I can see Daniel has his work cut out for him.&lt;/p&gt;  &lt;p&gt;The part that makes me see red is that when you look at the 3600 lines of JavaScript, you learn that essentially you have been served “everything”.&amp;#160; The scripts look at the URL you are on and determine what to display and how to display it.&amp;#160; They look at the cookies and determine what ads to serve up (and damn is there a lot of ad code).&amp;#160; They contain huge blocks of HTML code depending on what section you are in.&amp;#160; For example, apparently, there is something called a “dashboard”, which is customized to whatever section you’re in.&amp;#160; There’s Business &amp;amp; Travel, Boat &amp;amp; Beach, Golf, and Schoolday.&amp;#160; Guess what?&amp;#160; you got served the HTML for all four dashboards, and your browser will determine which gets displayed!&amp;#160; Also, your browser figures out where you came from and displays special graphics depending on it, like if you came from Google or from Home Depot.&amp;#160; and if you come from Home Depot and there’s a storm, you get different graphics.&lt;/p&gt;  &lt;p&gt;I don’t have a problem with most of that.&amp;#160; It’s clever and creative to vary the look at feel according to your partners and tie it in to the current weather.&amp;#160; But the base problem is: this can all be done on the server.&amp;#160; Looking at the URL, looking at the cookies, showing and hiding elements of the page based on those values.&amp;#160; It’s like code from 1990 – it’s not even ASP-grade code.&amp;#160; Even your typical ASP programmer would filter out the HTML for sections that aren’t relevant.&lt;/p&gt;  &lt;p&gt;I just don’t get it.&amp;#160; It absolutely boggles the mind that a major web site could have a page that is so grossly inefficient as to possibly cripple the web servers that serve it.&amp;#160; And can you imagine the bandwidth costs?&amp;#160; The web page code specifically forces you to get all the linked scripts using what they term “cache-busting”.&amp;#160; I’m starting to feel ill again, so I’m going to stop now.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=274" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Observations/default.aspx">Observations</category></item><item><title>Ok, Now We’re Talking</title><link>http://soapitstop.com/blogs/fleamarket/archive/2009/02/19/ok-now-we-re-talking.aspx</link><pubDate>Thu, 19 Feb 2009 02:07:37 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:270</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=270</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2009/02/19/ok-now-we-re-talking.aspx#comments</comments><description>&lt;p&gt;I suppose, like many companies, we’re trying to stay under the radar from the roving hammers of economic suckdom.&amp;#160; I also think we’re doing pretty well at it.&amp;#160; Possibly like other companies, we are taking the opportunity to completely rethink a core business need: communication.&lt;/p&gt;  &lt;p&gt;I am confident that anyone who spends a decent time with an employer eventually will say “communication in our company isn’t that great.”&amp;#160; It’s probably inevitable that as a company grows, the individual teams focus harder on what they are good at, maybe because of time constraints, maybe corporate culture turning introverted, maybe something else.&amp;#160; Anyway, it happens to the best.&lt;/p&gt;  &lt;p&gt;It’s also something I have a decent interest in.&amp;#160; I enjoy sharing knowledge and information and sometimes have felt frustrated that there wasn’t a decent outlet for me to do so.&amp;#160; Well, like they say, be careful what you wish for.&amp;#160; Seemingly overnight our company has embraced three new initiatives that will hopefully foster communication.&lt;/p&gt;  &lt;p&gt;The first one is an installation of Microsoft Office Communication Server.&amp;#160; That’s a big name for a little service: IM.&amp;#160; Well, MOCS (ahhh… acronyms) does a lot more than just Instant Messaging, we’re using video conferencing and other Live Meeting functions too. But the one that I cared about was IM.&amp;#160; Email is just so heavy to ask a simple question or send a code sample.&lt;/p&gt;  &lt;p&gt;MOCS was decided upon after trying out three different video conferencing systems.&amp;#160; This was decided within about a week.&amp;#160; So within two weeks, we had a new communication and conferencing solution.&lt;/p&gt;  &lt;p&gt;Back to the original point, the next thing we adopted was a centralized bug tracking system, BugTracker.NET.&amp;#160; This was a surprise to me, because I downloaded it as a simple replacement to my spiral-bound notebook.&amp;#160; I’ve been writing things down for years now and have recently learned that it doesn’t help me at all once I turn the page.&amp;#160; Going back a year in my notes, I logged 60 open issues into BugTracker.&lt;/p&gt;  &lt;p&gt;I explained to my boss what I was doing, he spent about 30 minutes with it and said that this was the new standard for the department.&amp;#160; So, within a day, we had a new issue tracking system for hardware and software issues. &lt;/p&gt;  &lt;p&gt;Thirdly, during a brainstorm session on how our department can be more friendly to our customers, the end users, it was suggested we maintain blogs.&amp;#160; This was pretty exciting to me because it opened the door to things I really wanted, like support forums and wiki knowledge bases.&amp;#160; But blogging is a start.&lt;/p&gt;  &lt;p&gt;I was given the lead for it and selected Community Server since I had experience in maintaining one and using one (here!).&amp;#160; So within a day, we had set up an online community for our department.&amp;#160; Only our department will be blogging initially, but we were challenged to set the bar high for the rest of the company.&amp;#160; I expect other departments will quickly embrace the blog concept.&lt;/p&gt;  &lt;p&gt;So let’s recap.&amp;#160; We’re a five-person IT staff supporting over 300 users at 45 locations.&amp;#160; On the request of our new leadership, we evaluated, selected, installed a corporate collaboration system; implemented what can easily become our corporate Intranet; and started tracking issues department-wide, answering the question, “where do we stand”.&amp;#160; All this in the span of a few weeks, while still supporting the users.&amp;#160; We’ve had a little time to absorb these changes, but looking back, this is a major shift for a company.&amp;#160; These kinds of changes usually happen over months.&lt;/p&gt;  &lt;p&gt;Next week will be presentations on what we’ve done.&amp;#160; I’m not sure how many heads will explode.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=270" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ramblings/default.aspx">Ramblings</category></item><item><title>Recurring Events in SQL</title><link>http://soapitstop.com/blogs/fleamarket/archive/2008/12/12/recurring-events-in-sql.aspx</link><pubDate>Fri, 12 Dec 2008 23:02:48 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:267</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=267</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2008/12/12/recurring-events-in-sql.aspx#comments</comments><description>&lt;p&gt;I recently had a little piece of SQL code that I thought I would post and it reminded me of something I did a long time ago (5 yrs) and thought I&amp;#39;d write something on it.&amp;#160; Anyway, first here&amp;#39;s the little piece without much celebration.&lt;/p&gt;  &lt;p&gt;This SQL code answers the question &amp;quot;What date is the third Wednesday in November 2008?&amp;quot;&amp;#160; This code could be wrapped in a function pretty easily.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;declare&lt;/span&gt; @&lt;span class="kwrd"&gt;month&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;,@&lt;span class="kwrd"&gt;year&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;,@weekday &lt;span class="kwrd"&gt;int&lt;/span&gt;,@weekOffset &lt;span class="kwrd"&gt;int&lt;/span&gt;

&lt;span class="kwrd"&gt;set&lt;/span&gt; @&lt;span class="kwrd"&gt;month&lt;/span&gt;=11 &lt;span class="rem"&gt;-- (Month of date to check) &lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @&lt;span class="kwrd"&gt;year&lt;/span&gt;=2008 &lt;span class="rem"&gt;-- (Year of date to check)&lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @weekday=5 &lt;span class="rem"&gt;-- 1-7 (Sun-Sat)&lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @weekOffset=1 &lt;span class="rem"&gt;-- 1-5 (Week of month)&lt;/span&gt;

&lt;span class="kwrd"&gt;declare&lt;/span&gt; @currentMonth datetime
&lt;span class="kwrd"&gt;declare&lt;/span&gt; @firstDay &lt;span class="kwrd"&gt;int&lt;/span&gt;
&lt;span class="kwrd"&gt;declare&lt;/span&gt; @newDate datetime

&lt;span class="rem"&gt;-- get the first day of the month&lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @currentMonth=&lt;span class="kwrd"&gt;cast&lt;/span&gt;(&lt;span class="kwrd"&gt;cast&lt;/span&gt;(@&lt;span class="kwrd"&gt;month&lt;/span&gt; &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;)+&lt;span class="str"&gt;&amp;#39;/1/&amp;#39;&lt;/span&gt;+&lt;span class="kwrd"&gt;cast&lt;/span&gt;(@&lt;span class="kwrd"&gt;year&lt;/span&gt; &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; datetime)
&lt;span class="kwrd"&gt;set&lt;/span&gt; @firstDay=datepart(dw,@currentmonth)

&lt;span class="rem"&gt;-- Add the number of days from the first day&lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @newDate=dateadd(dd,7*(@weekOffset-1)+
    &lt;span class="kwrd"&gt;case&lt;/span&gt; 
        &lt;span class="kwrd"&gt;when&lt;/span&gt; @weekday&amp;gt;=@firstDay &lt;span class="kwrd"&gt;then&lt;/span&gt; @weekday-@firstDay
        &lt;span class="kwrd"&gt;when&lt;/span&gt; @weekday&amp;lt;@firstDay &lt;span class="kwrd"&gt;then&lt;/span&gt; 7+@weekday-@firstDay
    &lt;span class="kwrd"&gt;end&lt;/span&gt;, @currentmonth)

&lt;span class="kwrd"&gt;select&lt;/span&gt; @newdate&lt;/pre&gt;

&lt;p&gt;The bigger idea I had was for recurring events in SQL, like for a calendar.&amp;#160; Assume the following structure of an event table&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; dbo.Events(
    ID &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;IDENTITY&lt;/span&gt;(1,1) &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt; ,
    StartDate datetime,
    EndDate datetime,
    Title &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255),
    Description &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(2000),
    RepeatValue &lt;span class="kwrd"&gt;char&lt;/span&gt;(1),
    RepeatInterval &lt;span class="kwrd"&gt;int&lt;/span&gt;
) &lt;/pre&gt;

&lt;p&gt;So you have a bunch of events defined that start and end on a range of dates.&amp;#160; The RepeatValue would be: D,W,M,Y for Day, Week, Month, Year.&amp;#160; The RepeatInterval would be the number of Days/Weeks/Months between repeats.&amp;#160; Add in some sample data&lt;/p&gt;

&lt;pre class="csharpcode"&gt;insert events &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;1/1/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;12/31/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;Each Month All Year&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt;,1
insert events &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;1/1/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;6/30/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;Bi-weekly Half Year&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt;,2
insert events &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;7/1/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;12/31/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;Weekly Half Year&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt;,1
insert events &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;2/1/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;3/1/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;Every other Day in Feb&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;,2
insert events &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;7/4/08&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;12/31/2999&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;July 4th&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt;,1&lt;/pre&gt;

&lt;p&gt;This is the stored proc I came up with to return the events for a given month:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;Procedure&lt;/span&gt; [dbo].[sp_ListRecurringCalendarEvents]
@viewdate datetime
&lt;span class="kwrd"&gt;as&lt;/span&gt;

&lt;span class="kwrd"&gt;set&lt;/span&gt; nocount &lt;span class="kwrd"&gt;on&lt;/span&gt;

&lt;span class="kwrd"&gt;declare&lt;/span&gt; @checkdate datetime

&lt;span class="kwrd"&gt;create&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; #tempCalendar(
    id &lt;span class="kwrd"&gt;int&lt;/span&gt;,
    startdate datetime,
    enddate datetime,
    title &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255),
    recurrance &lt;span class="kwrd"&gt;bit&lt;/span&gt; &lt;span class="kwrd"&gt;default&lt;/span&gt; 0
)

&lt;span class="rem"&gt;-- Insert Standard events&lt;/span&gt;
insert #tempCalendar
&lt;span class="kwrd"&gt;select&lt;/span&gt; e.id,e.startdate,e.enddate,e.title,0
&lt;span class="kwrd"&gt;from&lt;/span&gt; events e
&lt;span class="kwrd"&gt;where&lt;/span&gt; datepart(mm,e.startdate)=datepart(mm,@viewdate) 
    &lt;span class="kwrd"&gt;and&lt;/span&gt; datepart(yy,e.startdate)=datepart(yy,@viewdate)
    &lt;span class="kwrd"&gt;and&lt;/span&gt; repeatinterval=0

&lt;span class="rem"&gt;-- Insert all recurrances&lt;/span&gt;
&lt;span class="kwrd"&gt;set&lt;/span&gt; @checkdate=&lt;span class="kwrd"&gt;cast&lt;/span&gt;(&lt;span class="kwrd"&gt;cast&lt;/span&gt;(datepart(mm,@viewdate) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;) 
    + &lt;span class="str"&gt;&amp;#39;/1/&amp;#39;&lt;/span&gt; 
    + &lt;span class="kwrd"&gt;cast&lt;/span&gt;(datepart(yy,@viewdate) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; datetime)

&lt;span class="rem"&gt;-- Loop through each day in month and see if it is a recurrance&lt;/span&gt;
&lt;span class="kwrd"&gt;while&lt;/span&gt; datepart(mm,@viewdate)=datepart(mm,@checkdate)
    &lt;span class="kwrd"&gt;begin&lt;/span&gt;
    insert #tempCalendar
    &lt;span class="kwrd"&gt;select&lt;/span&gt; e.id,
    &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(dd,datediff(dd,startdate,@checkdate),startdate)
     &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(ww,datediff(ww,startdate,@checkdate),startdate)
     &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(mm,datediff(mm,startdate,@checkdate),startdate)
     &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(yy,datediff(yy,startdate,@checkdate),startdate)
    &lt;span class="kwrd"&gt;end&lt;/span&gt;,
    e.enddate,e.title,
    &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; @checkdate=e.startdate &lt;span class="kwrd"&gt;then&lt;/span&gt; 0 &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
    &lt;span class="kwrd"&gt;from&lt;/span&gt; events e
    &lt;span class="kwrd"&gt;where&lt;/span&gt; e.RepeatInterval&amp;lt;&amp;gt;0 
        &lt;span class="kwrd"&gt;and&lt;/span&gt;
        &lt;span class="rem"&gt;-- Daily (Check to see if the number of day interval matches&lt;/span&gt;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (&lt;span class="kwrd"&gt;cast&lt;/span&gt;(datediff(dd,startdate,@checkdate) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)
            /&lt;span class="kwrd"&gt;cast&lt;/span&gt;(RepeatInterval &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt; =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (datediff(dd,startdate,@checkdate)/RepeatInterval) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
        &lt;span class="kwrd"&gt;and&lt;/span&gt; 
        &lt;span class="rem"&gt;-- Weekly (check to see if the week interval matches and the weekday is the same)&lt;/span&gt;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (&lt;span class="kwrd"&gt;cast&lt;/span&gt;(datediff(ww,startdate,@checkdate) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)
            /&lt;span class="kwrd"&gt;cast&lt;/span&gt;(RepeatInterval &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt; =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (datediff(ww,startdate,@checkdate)/RepeatInterval) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
            &lt;span class="kwrd"&gt;and&lt;/span&gt; &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dw,startdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;    =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dw,@checkdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
        &lt;span class="kwrd"&gt;and&lt;/span&gt; 
        &lt;span class="rem"&gt;-- Monthly (check to see that the month interval is the same and the day of the month is the same)&lt;/span&gt;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (&lt;span class="kwrd"&gt;cast&lt;/span&gt;(datediff(mm,startdate,@checkdate) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)
            /&lt;span class="kwrd"&gt;cast&lt;/span&gt;(RepeatInterval &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt;)) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt; =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; (datediff(mm,startdate,@checkdate)/RepeatInterval) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
            &lt;span class="kwrd"&gt;and&lt;/span&gt; &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dd,startdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;    =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dd,@checkdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
        &lt;span class="kwrd"&gt;and&lt;/span&gt; 
        &lt;span class="rem"&gt;-- Yearly (Check to see if the day of the year is the same)&lt;/span&gt;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dy,startdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt; =
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; datepart(dy,@checkdate) &lt;span class="kwrd"&gt;else&lt;/span&gt; 1 &lt;span class="kwrd"&gt;end&lt;/span&gt;
        &lt;span class="kwrd"&gt;and&lt;/span&gt; 
        e.startdate &amp;lt;= &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(dd,datediff(dd,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(ww,datediff(ww,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(mm,datediff(mm,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(yy,datediff(yy,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;end&lt;/span&gt; 
        &lt;span class="kwrd"&gt;and&lt;/span&gt; 
        e.enddate &amp;gt;= &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(dd,datediff(dd,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;W&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(ww,datediff(ww,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;M&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(mm,datediff(mm,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;when&lt;/span&gt; RepeatValue=&lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt; &lt;span class="kwrd"&gt;then&lt;/span&gt; dateadd(yy,datediff(yy,startdate,@checkdate),startdate)
            &lt;span class="kwrd"&gt;end&lt;/span&gt;

    &lt;span class="rem"&gt;-- Increment the date&lt;/span&gt;
    &lt;span class="kwrd"&gt;set&lt;/span&gt; @checkdate=dateadd(dd,1,@checkdate)

    &lt;span class="kwrd"&gt;end&lt;/span&gt;    

&lt;span class="rem"&gt;-- return the results&lt;/span&gt;
&lt;span class="kwrd"&gt;select&lt;/span&gt; * &lt;span class="kwrd"&gt;from&lt;/span&gt; #tempCalendar

&lt;span class="rem"&gt;-- Clean up&lt;/span&gt;
&lt;span class="kwrd"&gt;drop&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; #tempCalendar&lt;/pre&gt;

&lt;p&gt;The proc is called passing a date within the month to be displayed.&amp;#160; The results include the ID of the event (for linking), the start date of the event, the end date of the event (not so relevant), the event title, and whether this is a recurring event or not (in case you want to display it differently or disable editing of events that aren&amp;#39;t the original).&lt;/p&gt;

&lt;p&gt;So, many years later, I still find it intriguing that I was doing stuff like that.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=267" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>Your Code Is Very Important To Us, Please Continue To Wait...</title><link>http://soapitstop.com/blogs/fleamarket/archive/2008/11/25/your-code-is-very-important-to-us-please-continue-to-wait.aspx</link><pubDate>Wed, 26 Nov 2008 00:41:52 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:264</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=264</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2008/11/25/your-code-is-very-important-to-us-please-continue-to-wait.aspx#comments</comments><description>&lt;p&gt;It was asked of me once: &lt;em&gt;Why isn&amp;#39;t my &amp;quot;please wait&amp;quot; form doing anything?&lt;/em&gt;&amp;nbsp; The form had an animation, but the animation never moved.&amp;nbsp; The main form code would show the &amp;quot;please wait&amp;quot; form, run some code, then hide the &amp;quot;please wait&amp;quot; form.&amp;nbsp; As it turned out, the &amp;quot;please wait&amp;quot; form was being blocked by a database call and some other stuff in the main form.&amp;nbsp; There was never a chance for a DoEvents or redraw or anything.&lt;/p&gt; &lt;p&gt;The quick answer is, you have to show the other form in another thread, so it can operate freely and redraw itself.&amp;nbsp; The longer answer is, you have to deal with threading.&lt;/p&gt; &lt;p&gt;Threading is very easy in VB.NET, but some people want answers, not lessons, so I ended up writing this quick class to show a form in another thread.&amp;nbsp; It&amp;#39;s pretty simple.&amp;nbsp; You instantiate the class by passing in an instance of your &amp;quot;please wait&amp;quot; form , then call show(), do your work, then call hide().&amp;nbsp; Like so:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; f &lt;span class="kwrd"&gt;as&lt;/span&gt; N&lt;span class="kwrd"&gt;ew&lt;/span&gt; BackgroundForm(&lt;span class="kwrd"&gt;new&lt;/span&gt; frmWait)

f.Show()
&lt;span class="rem"&gt;&amp;#39; Do some stuff&lt;/span&gt;
f.Hide()&lt;/pre&gt;
&lt;p&gt;Only one caveat: you can&amp;#39;t have the variable for the BackgroundForm class at the class level.&amp;nbsp; It must be declared, instantiated, and used in the same method.&amp;nbsp; Otherwise, you will get Cross-Threading errors.&lt;/p&gt;
&lt;p&gt;So, here&amp;#39;s the class you can use for yourself, if you prefer answers to lessons.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; BackgroundForm
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; displayForm &lt;span class="kwrd"&gt;As&lt;/span&gt; Form
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; t &lt;span class="kwrd"&gt;As&lt;/span&gt; System.Threading.Thread
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; isActive &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;
    &lt;span class="kwrd"&gt;Shared&lt;/span&gt; lockObject &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;

    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt;(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; f &lt;span class="kwrd"&gt;As&lt;/span&gt; Form)
        displayForm = f
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Show()
        t = &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Threading.Thread(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; ShowForm)
        t.IsBackground = &lt;span class="kwrd"&gt;True&lt;/span&gt;
        t.Start()
        isActive = &lt;span class="kwrd"&gt;True&lt;/span&gt;

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Hide()
        isActive = &lt;span class="kwrd"&gt;False&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; ShowForm()
        displayForm.Show()

        &lt;span class="kwrd"&gt;Do&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt; isActive &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; displayForm.Visible
            System.Threading.Thread.Sleep(100)
            &lt;span class="kwrd"&gt;SyncLock&lt;/span&gt; lockObject
            Application.DoEvents()
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;SyncLock&lt;/span&gt;
        &lt;span class="kwrd"&gt;Loop&lt;/span&gt;

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="kwrd"&gt;End&lt;/span&gt; Class&lt;/pre&gt;
&lt;p&gt;I made a slight change to the code to protect against thread stomping.&amp;nbsp; If you have an animated GIF in your &amp;quot;please wait&amp;quot; form, and you have a more than one &amp;quot;please wait&amp;quot; form active at once, there is the chance you will get a &amp;quot;object is in use elsewhere&amp;quot; error.&amp;nbsp; This happens when the image for the current form is being changed - in the DoEvents - but another form is being closed/disposed, taking the same image with it.&lt;/p&gt;
&lt;p&gt;By wrapping the DoEvents in a SyncLock that is shared among all instances, this is prevented.&amp;nbsp; I couldn&amp;#39;t get the error to happen unless I opened over 20 windows and had them closing at scheduled times, but your luck may be worse.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=264" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>Autosize.  No, not the control, the text.</title><link>http://soapitstop.com/blogs/fleamarket/archive/2008/11/16/autosize-no-not-the-control-the-text.aspx</link><pubDate>Sun, 16 Nov 2008 16:37:31 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:262</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=262</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2008/11/16/autosize-no-not-the-control-the-text.aspx#comments</comments><description>&lt;p&gt;It&amp;#39;s nice that .NET controls have an auto-size property so you don&amp;#39;t have to worry about overflow and all.&amp;#160; But what about cases where you have a fixed layout?&amp;#160; Well, that&amp;#39;s simple, you turn autosize off and fix the control to the size you need.&lt;/p&gt;  &lt;p&gt;That&amp;#39;s half the story.&amp;#160; What about the text that&amp;#39;s inside it?&amp;#160; Now you know I&amp;#39;m talking to marketing people when I say that there are times you want the text to be as big as possible within that control.&amp;#160; But you can&amp;#39;t just set the font to a huge size, because sometimes you&amp;#39;ll have more text to display and the font size must sadly be reduced.&lt;/p&gt;  &lt;p&gt;To accommodate this, I made a quick method that brute-forces the correct font size in the control.&amp;#160; basically, stepping down the size of the font until it fits.&amp;#160; I know loops like this are cheap, poor programming, and I did give consideration to doing some hard math to calculate the proper font size based on the initial size, but sometimes not getting hung up on performance can be liberating.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; ResizeText(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; Control)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; currentSize &lt;span class="kwrd"&gt;As&lt;/span&gt; Size
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; currentFont &lt;span class="kwrd"&gt;As&lt;/span&gt; Font

        currentFont = c.Font

        &lt;span class="kwrd"&gt;Do&lt;/span&gt;
            currentSize = TextRenderer.MeasureText(c.Text, currentFont, _
                c.Size, TextFormatFlags.WordBreak)

            &lt;span class="kwrd"&gt;If&lt;/span&gt; currentSize.Width &amp;gt; (c.Width - c.Margin.Horizontal) _
                &lt;span class="kwrd"&gt;OrElse&lt;/span&gt; currentSize.Height &amp;gt; (c.Height - c.Margin.Vertical) &lt;span class="kwrd"&gt;Then&lt;/span&gt;

                currentFont = &lt;span class="kwrd"&gt;New&lt;/span&gt; Font(currentFont.FontFamily, _
                    &lt;span class="kwrd"&gt;CSng&lt;/span&gt;(currentFont.Size - 0.5), currentFont.Style, currentFont.Unit)
            &lt;span class="kwrd"&gt;Else&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Do&lt;/span&gt;

            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Loop&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt; currentFont.Size &amp;gt;= 1

        c.Font = currentFont

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=262" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item><item><title>Casting Upwards</title><link>http://soapitstop.com/blogs/fleamarket/archive/2008/11/04/casting-upwards.aspx</link><pubDate>Wed, 05 Nov 2008 00:52:40 GMT</pubDate><guid isPermaLink="false">c84fe871-9be4-49f2-9abc-6118b8cda40a:261</guid><dc:creator>anachostic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://soapitstop.com/blogs/fleamarket/rsscomments.aspx?PostID=261</wfw:commentRss><comments>http://soapitstop.com/blogs/fleamarket/archive/2008/11/04/casting-upwards.aspx#comments</comments><description>&lt;p&gt;When binding business objects to a datagrid, often you have a need to display some information that is not directly exposed by the object itself.&amp;#160; Maybe it&amp;#39;s a calculated value, maybe it&amp;#39;s something nested deeper in the object.&amp;#160; When faced with this issue, there are a few different action paths you can take.&amp;#160; You can add extra read-only properties to your business object to support the extra view information.&amp;#160; You can create a new class that inherits from the class you are displaying and put the extra properties in there.&amp;#160; Or you can handle the CellFormatting event in the datagrid and change the displayed values manually.&amp;#160; One of the downsides of using a new derived class with extra properties is that you can&amp;#39;t cast a base class to it.&amp;#160; You could cast down to the base class, but no casting up. &lt;/p&gt;  &lt;p&gt;Here is a technique that is closest to the second option listed above and side-steps the upcasting problem.&amp;#160; I dislike the first option because it clutters the business object with UI-specific code.&amp;#160; Going with option 2 is only slightly better, while you can populate the correct display-specific object and return it from your business logic layer, either you have to have a method that return the derived type, or you will have to cast it to its correct type in the UI.&amp;#160; Even then, your business layer still contains UI logic. &lt;/p&gt;  &lt;p&gt;So, keeping things separated, the derived display-specific class should be defined in the UI layer.&amp;#160; This means it will have extra read-only properties for use with databinding.&amp;#160; The business layer will return the basic object(s), so it will be up to us to convert these to UI-friendly versions.&amp;#160; There are two problems with converting the object: not all the object state may be exposed via public properties, and those properties may contain logic.&amp;#160; It would be best to copy the object by its internal state - private variables. &lt;/p&gt;  &lt;p&gt;On first thought, working with the private variables means the code must be inside the source object and the destination object.&amp;#160; This would be tedious to do, passing in the destination object, then sending the source object&amp;#39;s private variables to the destination so the destination object can manipulate its own private variables.&amp;#160; Yuck.&amp;#160; However, using Reflection, the job gets a whole lot easier. &lt;/p&gt;  &lt;p&gt;Here&amp;#39;s a small class with a method to convert one class to another by copying its private and public fields.&amp;#160; The properties are intentionally excluded since they may contain logic that modifies the internal state.&amp;#160; You should use this technique with care and know exactly what it does and does not do.&amp;#160; Basically, it copies values from one instance of a class to another.&amp;#160; This is fine for simple classes, but it&amp;#39;s not going to resolve references for you. &lt;/p&gt;  &lt;p&gt;Consider ClassA with a private field of type ClassB.&amp;#160; ClassB maintains a private variable with a reference to ClassA, so that it can manipulate all of its &amp;quot;parent&amp;#39;s&amp;quot; state and logic.&amp;#160; If you use this technique to cast ClassA to ClassAA, because you want an extra property to display some info from ClassB, you&amp;#39;re in for some fun results if you change some data in ClassAA.&amp;#160; This is because ClassB still has a reference to ClassA, not ClassAA. &lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; UpCaster
    &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; CastUp(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sourceObj &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; destinationObj &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; values &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;Object&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; props() &lt;span class="kwrd"&gt;As&lt;/span&gt; Reflection.FieldInfo 

        props = sourceObj.&lt;span class="kwrd"&gt;GetType&lt;/span&gt;.GetFields(Reflection.BindingFlags.NonPublic _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.&lt;span class="kwrd"&gt;Static&lt;/span&gt; _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.Instance _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.&lt;span class="kwrd"&gt;Public&lt;/span&gt;) 

        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; p &lt;span class="kwrd"&gt;As&lt;/span&gt; Reflection.FieldInfo &lt;span class="kwrd"&gt;In&lt;/span&gt; props
            values.Add(p.Name, p.GetValue(sourceObj))
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; 

        props = destinationObj.&lt;span class="kwrd"&gt;GetType&lt;/span&gt;.GetFields(Reflection.BindingFlags.NonPublic _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.&lt;span class="kwrd"&gt;Static&lt;/span&gt; _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.Instance _
            &lt;span class="kwrd"&gt;Or&lt;/span&gt; Reflection.BindingFlags.&lt;span class="kwrd"&gt;Public&lt;/span&gt;) 

        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; p &lt;span class="kwrd"&gt;As&lt;/span&gt; Reflection.FieldInfo &lt;span class="kwrd"&gt;In&lt;/span&gt; props
            &lt;span class="kwrd"&gt;If&lt;/span&gt; values.ContainsKey(p.Name) &lt;span class="kwrd"&gt;Then&lt;/span&gt; p.SetValue(destinationObj, values(p.Name))
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; 

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; 

&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt;&lt;/pre&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=261" width="1" height="1"&gt;</description><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Ideas/default.aspx">Ideas</category><category domain="http://soapitstop.com/blogs/fleamarket/archive/tags/Code+Samples/default.aspx">Code Samples</category></item></channel></rss>