Critical Development

Language design, framework development, UI design, robotics and more.

Archive for the ‘Invention-A-Day’ Category

Visual Studio Macro: Locate Item in Solution Explorer on Demand

Posted by Dan Vanderboom on March 21, 2008

[ For an updated macro that works best with VS2008 and VS2010, see the followup article. ]

By default, Visual Studio’s Solution Explorer will update its selected item based on the currently active document.  This is occassionally useful when exploring unfamiliar code, but it’s annoying when it’s always on, bouncing around as you navigate through larger solutions.

Do you want to disable project item tracking?

 

Go to Tools—>Options, expand Projects and Solutions, select General, and then uncheck the box next to Track Active Item in Solution Explorer.

But what if you’re looking at a document, and you want to know where in Solution Explorer it’s located?  Unfortunately, you would have to go back into Tools—>Options, …, turn that option back on, locate the project item, and then turn it back off again.

This is very inconvenient.  What would be ideal is a button or hot key that would jump to that item in Solution Explorer just once, on demand.  “Where’s the corresponding project item for this document?  Find it and then don’t track after that.”

After about two hours of messing around with the VS SDK, trying to read the documentation, finding out that this particular option isn’t available for manipulation through automation, and resolving to figure out another way to do it, I finally accomplished this goal and I’m happy to share the macro that I created.

Don’t know how to create a macro?

 

Adding a macro is easy.  First open the Macro Explorer.  Press Alt-F8, or if you’ve remapped your keys, go to Tools—>Macros—>Macro Explorer.  You’ll probably have a project in there called MyMacros.  If not, right-click on Macros and select New Macro Project…  A window pops up, and you can enter a project name.  Once you have selected or created a macro project, right click on the project name and select New module…  I named mine Utilities.  Right click on the module name and select Edit.  You should now see a VB code editor window.

Copy the following code into the editor and press Ctrl-S to save it.

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90

Public Module Utilities
    Public Sub TrackProjectItem()
        Dim solution As Solution2 = DTE.Solution
        If Not solution.IsOpen OrElse DTE.ActiveDocument Is Nothing Then Return

        solution.FindProjectItem(DTE.ActiveDocument.FullName).ExpandView()

        Dim FileName As String = DTE.ActiveDocument.FullName

        Dim SolutionExplorerPath As String
        Dim items As EnvDTE.UIHierarchyItems = DTE.ToolWindows.SolutionExplorer.UIHierarchyItems
        Dim item As Object = FindItem(items, FileName, SolutionExplorerPath)

        If item Is Nothing Then
            MsgBox("Couldn't find the item in Solution Explorer.")
            Return
        End If

        DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
        DTE.ActiveWindow.Object.GetItem(SolutionExplorerPath).Select(vsUISelectionType.vsUISelectionTypeSelect)
    End Sub

    Public Function FindItem(ByVal Children As UIHierarchyItems, ByVal FileName As String, ByRef SolutionExplorerPath As String) As Object
        For Each CurrentItem As UIHierarchyItem In Children
            Dim TypeName As String = Microsoft.VisualBasic.Information.TypeName(CurrentItem.Object)
            If TypeName = "ProjectItem" Then
                Dim projectitem As EnvDTE.ProjectItem = CType(CurrentItem.Object, EnvDTE.ProjectItem)
                Dim i As Integer = 1
                While i <= projectitem.FileCount
                    If projectitem.FileNames(i) = FileName Then
                        SolutionExplorerPath = CurrentItem.Name
                        Return CurrentItem
                    End If
                    i = i + 1
                End While
            End If

            Dim ChildItem As UIHierarchyItem = FindItem(CurrentItem.UIHierarchyItems, FileName, SolutionExplorerPath)
            If Not ChildItem Is Nothing Then
                SolutionExplorerPath = CurrentItem.Name + "\" + SolutionExplorerPath
                Return ChildItem
            End If
        Next
    End Function
End Module

 

Now let’s hook it up to a keyboard hot key to make it super fast to access.  If you open Tools—>Options, expand Environment, select Keyboard, and in the text box labeled Show commands containing, type part of the macro name, such as TrackProjectItem.  You’ll see your new macro in the list highlighted.  In the dropdown control labeled Use new shortcut in, select Text Editor.  Click on the box that says Press shortcut keys, and press a key combination.  I chose Alt-T (for Track), which was available in that context to my surprise.

Try it out.  Open up a few code or XML windows.  Make one of those windows active and press your hot key.  The item in Solution Explorer that corresponds to the current document window will activate.

 

Tags: , , ,

Advertisements

Posted in Invention-A-Day, Visual Studio, Visual Studio Extensibility | 47 Comments »

Windows Forms Data Binding: Language-Level Support Needed

Posted by Dan Vanderboom on March 6, 2008

I’ve been busy building an MVC framework for the past few weeks, and one of the aspects of this framework I want to make as transparent as possible is data binding.  I want to use automatic data binding between a control property in the view and a property in the controller.  This is much more difficult than it needs to be.  Because my controller inherits from a base class, it has access to a helper method to raise the PropertyChanged event in the INotifyPropertyChanged interface, which makes things a tad easier.

LastNameProperty

Here is what that helper method looks like:

SetProperty

Even with a code snippet to generate the property (with the call to SetProperty), I don’t like it.  For one or two properties, it’s not too bad, but when you have dozens of properties that need to notify another object of changes—multiplied by dozens of controllers and views, it creates code bloat.  The string “LastName”, lacking strong typing, is also less than perfect.

What I really want is to combine automatic properties (a new feature in C# 3.0) with a new language keyword like “notify” that would hook the SetProperty logic into the setter.  Like this:

public notify string LastName { get; set; }

The same keyword for collection types, producing slightly different notification effects, would be nice as well, so I wouldn’t have to use BindingList<T> specifically.

public notify List<Customer> Customers { get; set; }

But alas, I’ll have to do it the hard way.  I’ve been considering using an aspect weaver to stitch in this logic in a post-build task.  It would work, but the notifications wouldn’t be fired during debugging, and that’s just not acceptable.

Data binding is extremely important, and WPF has—from what I’ve seen so far—done a great job implementing it.  For those of us stuck in Windows Forms (I develop applications for Windows Mobile devices primarily), some other alternatives are long overdue.

I’ve been able to mimic a small part of the capabilities of WPF data binding, specifically support for binding paths such as “Controller.Computer.ProcessorName”.  In Windows Forms data binding, if you change which object Controller.Computer points to, your user interface control will continue to reference the old Computer object’s ProcessorName property.  Not so good!  Using data binding paths, if you point Controller.Computer to a new Computer object, the UI control does an automatic rebinding to the new object’s ProcessorName property.  I then set the control’s Tag property to tell it the name of the control property and the name of the property to bind it to, like this: “Text=Controller.Customer.LastName”.  There have been a number of road blocks to making it work smoothly (such as dealing with null values, and null parent objects), but it does in fact work, is smooth and fast, and supports complex as well as simple data binding.

In a future blog post, I’ll describe the general design and hopefully also share some code.

Posted in Compact Framework, Data Binding, Invention-A-Day, Object Oriented Design, User Interface Design, Windows Forms | Leave a Comment »

Invention-A-Day: List Control Builder

Posted by Dan Vanderboom on January 6, 2008

I spent a few hours yesterday playing in WPF again, this time with data binding and list controls.  Every time I work with WPF, I get more excited, and am more impressed by what’s possible there.  I work with Windows Forms on mobile devices for a living, and list controls is one area that always seems to be lacking something.  I’ve used Resco’s AdvancedList for several years, and find that I can get it to do almost anything within reason in Windows Forms, but the API leaves a lot to be desired: it is unintuitive in several ways.

I’ve looked through the source code for several list controls, and they are complicated beasts.  Almost too complicated, I think, to be packaged up as a whole and delivered atomically as they are (though one can hardly blame them for delivering a complete solution).

Regardless of whether we’re talking WPF or Windows Forms (though I think WPF would support it much more easily), my invention is a list control system in which one can select options and write new components for different aspects or components within it.  With this list control builder, I would like to select a paging mechanism (virtualized, all-in-memory), a scrolling mechanism (scrollbars, grab-and-pull, accelerated-tug), a selecting mechanism (single, multiple, selection by selecting a control or double-tapping), a display style, and so on.  A wizard could guide the developer through the list’s creation, and the resulting configuration and behavior could then be saved as either a new style, or a generated control assembly, to appear in the toolbox as a new control.

Posted in Invention-A-Day, User Interface Design, Visual Studio | Leave a Comment »

Invention-A-Day: Visual Studio Virtual Asset Collection

Posted by Dan Vanderboom on January 6, 2008

One of the challenges of managing several large Visual Studio solutions with many shared projects is that related assets aren’t always located in the same place.  I use a querying system that inserts many queries inside rows of a table on the server.  This allows us to change synchronization queries without having to recompile the application.  These are loaded into the database through a database-building application.  Then we have template definitions for list controls which are loaded on handheld devices in a separate solution, and therefore a separate instance of Visual Studio.  Then there’s code to establish the data bindings, which is located elsewhere, and a few other pieces are spread here and there.  The result is that when I need to create a new list of data, I have to go to several different places to set it up.  I’m constantly jumping between instances of Visual Studio, different projects, editing template XML files and SQL queries and code files, etc.  And I keep thinking it would be nice to have all of this stuff in one place, at least for the purpose of creating and editing during development, even if they get distributed across several assemblies.

I use a file explorer tool called Directory Opus, which has the ability of defining “Collections”.  You can add files and folders to these named collections, and even though they’re spread across many different locations, you can access them all in one spot.

So here’s my invention today: a tool window in Visual Studio where you can define your own named collections, into which you can drag and drop items from Solution Explorer, or from files in other solutions.  Or better yet, a replacement for Solution Explorer that has this ability integrated into it.  Then in one place, I could see my list control templates, the queries that populate the list, the code for the workflow logic that uses it, both the view and its presenter (or controller) in an MVC/MVP pattern, images used in the list, and so on.

Posted in Invention-A-Day, User Interface Design, Visual Studio | Leave a Comment »

Visual Studio Add-In: Reference Sentinel

Posted by Dan Vanderboom on December 20, 2007

My article on Project Reference Oddness has been the most popular so far.  I like seeing the blog statistics, and I’m constantly observing the search terms people use to get to my blog.  I guess I shouldn’t have been surprised by the number of people having problems with references and searching for answers online.  It’s a pretty messed up system.

I’ve been contemplating writing an add-in for Visual Studio that would track and manage references, set some rules, and enforce them. I’d like to be able to specify that I use v3.1 of Library X across all projects in a solution. I’d then like to be able to make a change in one place (like a Reference Explorer) and have it update all projects in the solution. If one of the references changes outside of this system (for whatever reason), it should act as a sentinel, detecting the change and changing it back to what you defined in the Reference Explorer.  (It should also notify you that this has happened to help troubleshoot the root cause.)

It could also set reference paths.  By saving this information as an extension to the solution file, it could be checked into source control and shared with the rest of your development team.  This should eliminate the warnings and errors you get when you accidentally reference different versions of the same assembly.  It would also reduce the pain of creating a new branch or pulling code down to a new machine and having to spend a bunch of time setting the reference paths over and over again.

Am I missing anything?  What other reference pains could be alleviated?

Posted in Invention-A-Day, My Software, Visual Studio | 3 Comments »

Global ImageList Control – ImageListProxy

Posted by Dan Vanderboom on December 20, 2007

It would be normal for me to have already jumped forward to WPF and to leave Windows Forms behind, but being a Compact Framework developer, I don’t yet have that option.  Though I look forward to Silverlight, this won’t work for occassionally-connected or totally-disconnected mobile applications because Silverlight won’t work without some kind of back end server.  (Unless a certain company’s Windows Mobile ASP.NET server can support Silverlight, which would be awesome.  Someone in the .NET world needs to compete with Adobe’s FlashLite!)

One of the things I need to do is manage assets, such as graphic files.  Because the applications I write need that polished, commercial, and professional spit-and-polish, I am constantly including images into my user interfaces.  Sometimes these are stored in ImageList controls, to feed data-bound list controls and so on.  When you share common images across many forms, many views, many projects, such as checkboxes, question mark icons, etc., it’s a pain to have to include them over and over again.  Why not have an ImageList-derived component that acts as a proxy to a shared, global image list?  Images could be stored as resources in the project (or a resource assembly), or could be retrieved as files or database objects, but exposed from a single shared object to a collection of form-specific ImageListProxy objects.

The more cool stuff I read about WPF, the more I think that new controls, components, and other simple tools could be included in Windows Forms to accomplish many of the same goals.  To an extent, of course, but definitely worthwhile pursuing.  Windows Forms is going to be with us for a while longer.

Posted in Compact Framework, Invention-A-Day, Object Oriented Design | Leave a Comment »

Invention-A-Day: Social Networking Protocol and Super Client Shell

Posted by Dan Vanderboom on December 18, 2007

There has been an overwhelming explosion of social networking websites in the past several years.  Myspace, MS Live Spaces, Zaadz, Facebook, Flickr, LinkedIn, … the list goes on forever, it seems.  How many of these things do I need to create an account for, anyway?  Like I don’t already have a bunch of e-mail addresses to keep track of—now I need to check my social network sites for messages and connect to people I know (or those I’d like to meet).

I don’t know if this is an invention per se or if I’m just seeing the convergence of a trend, but with the huge amount of overlap in social networking services, I’m envisioning some kind of standardized protocol for publishing personal profiles, sharing group folders and web-page-zones, defining schemas and permissions for contacts and groups, etc.  Just as we’ve standardized on protocols for e-mail, web content management and syndication, file transfers, newsgroup article distribution, P2P content sharing, and other information technologies, I’d like to see a standard emerge for various aspects of what we call “social networking”.  I have many choices when it comes to Bittorrent client software, but each of those clients communicates on the same protocol over the same network, and so they’re interoperable.

This is the age of interoperability, is it not?  I’d like to define my profile once, and publish it to all of the social networking websites out there.  Better yet, give me a thick client with a beautiful cinematic experience WPF interface so that I can synchronize some of that data to use offline, sync it to my Windows Mobile phone, etc.  How many times do we really need to define a set of contacts?  In our thick client e-mail, our web mail, our company CRM, and each of our social networking sites?  How ubiquitous is the need now to share files with individuals or groups, for business or personal reasons?  All of these social technologies are now scattered and fragmented, with no coherent vision of pulling them all together, it seems.

What we need is a Super Client.  Imagine an extensible user interface shell like Outlook or Visual Studio, perhaps based on WPF Acropolis or a similar effort, into which modules can be plugged in.  Allow treeviews to be extended to include new nodes and context-menu options, etc., and all of this social technology plugged into together for deeper integration, shared but extensible schemas, and a common user experience.  Wherever I read and write e-mails, that’s where I want to read newsgroups and blogs, listen to podcasts, share photos, tasks, calendar appointments, contacts, Internet folders, and more.

In fact, why not make this an operating system service?  The ability to dock windows with/on/to each other, group them together, load and close them in persistent groups, and launch them from each other through simply-defined associations?

A unified Super Client user interface shell (or OS shell service) plus social protocol.  That’s my invention of the day.  Or my prediction.  Take your pick.

Posted in Invention-A-Day, Problem Modeling, User Interface Design | Leave a Comment »

Invention-A-Day: Ketchup-And-Mustard-In-One Bottle

Posted by Dan Vanderboom on December 17, 2007

I used to do something called Invention-A-Day, where’d I come up with at least one new gadget, service, business idea, etc., every day.  I’ve been slacking for a few months, but one came to me today.  It’s a ketchup-and-mustard-in-one bottle.  Two compartments for the two liquids, two nozzles, and some ability to open or close each valve.  With both nozzles pointing toward a center point, you could apply both condiments at the same time to your hamburger or brat.

The great thing about Invention-A-Day is that it requires no obligation to implement your idea, and it therefore becomes a fun game that loosens up the mind and encourages creativity.  As long as you believe your its original, your idea is good.  I can’t count the number of inventions I’ve made where I found out later they already existed.  In fact, that’s how I found my fretlight guitar.  After inventing it, I guessed that it would be such a great idea that someone had to have invented it already.  I was right, and a good thing, too!

Another advantage is that it gives you practice with design.  The more fun or exciting your idea is, the more likely you’ll pursue thinking about it, figure out how it would work, speculate about the obstacles, and so on.  Try it!  You might enjoy it!

Oh, and if you ever find one of my inventions out there already, post a comment and tell me about it.

Tags:

Posted in Invention-A-Day | 7 Comments »