So, it’s probably no secret that I’m a twitter addict.  Unlike a lot of twitter addicts, my addiction is not for celebrity sleaze or news updates.  Instead I use twitter as a social network much the way some people use Facebook or MySpace.  My friends and colleagues that are on twitter are generally technical in nature.  Having an in depth minute to minute relationship with these people has created a very tight-knit group of friends.  So much so that I travel as much as 7 hours several times per year just to catch up face-to-face.

Recently, I landed on a client that filters out twitter.com.  With no access via my computer, I undertook a deliberate and in depth search for a windows mobile client so that I could catch up on twitter (over my lunch break.)  I tried a few different applications but I was having trouble finding one that would perform well super lightning fast, contained an interface that was easy to use, and worked on my winmobile 6.1 device. 

Then came twikini.  It was referred to me by one of my friends that I met through twitter and I quickly installed it.  It is seriously the fastest running application I have on my phone.  It’s slick, easy to navigate, and plain simple to use.  It has multiple color schemes that allow me to customize the look and feel to allow me to use visual indicators to distinguish replies from standard feeds.  Additionally, it integrates twitpic images and links very well. 

Screenshot

I fully recommend trying twikini on the win mobile if you are interested in bettering your experience with twitter.


Posted in:   Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
admin posted on May 27, 2009 06:58

Recently, I’ve been working a lot with Silverlight.  I just finished writing a couple of controls that change the way that users interact with common data types.  With the recent advent of rich interfaces hosted on the web, an improvement in the way that users can interact with data is taking place.  So, I’m experimenting with a way to select ranges of information. 

When dealing with ranges, a classic HTML site may have a couple of drop downs that have a beginning and ending number, text, or date.  This interaction paradigm isn’t necessarily the best but it was the best that was available to us as developers.  People got used to it but it doesn’t mean that they like it. 

When a person fundamentally thinks of a range of somethings, they typically think horizontally or vertically.  A couple of dropdowns is not how they think.  If the range is a series of numeric values then the user wants to see the entire list of possible values and then have the values that he/she wants to select be highlighted.  Visually, this removes the responsibility of the person to determine if a number is between start and end.  They only have to make sure it’s highlighted. 

Here’s an example:

image

As you can see, I’m selecting 14 through 20.  Instantly, I know that 17 is in my range, I don’t have to look at two drop downs, compare them.  I also don’t have the error prone possibility of having the end number be less than my beginning number.  These types of paradigm shifts are going to happen now that we have richer user experience possibilities. 

When I started creating this control, the first thing I wanted to do was create an expandable block.  To do this, we’ve really got several controls. 

We have a Canvas that contains a Grid that has an empty border, and another border that contains a Grid that contains a Rectangle.

image

XAML:

  1: <Canvas x:Name="LayoutRoot" Background="Transparent">
  2:         <Grid Margin="0,2,0,2" MinWidth="20"
  3:                 x:Name="window" 
  4:                 VerticalAlignment="Center" MouseMove="WindowMouseMove" MouseLeftButtonDown="WindowMouseDown" MouseLeftButtonUp="WindowMouseUp" >
  5:             <Border CornerRadius="4,4,4,4" 
  6:                     Background="Transparent" 
  7:                     BorderBrush="Blue" BorderThickness="1" />
  8:             <Border CornerRadius="2,2,2,2" 
  9:                     Background="Transparent" Padding="4,0,4,0">
 10:                 <Grid x:Name="grd" Margin="3,0,3,0" MouseMove="BarMouseMove" MouseLeftButtonDown="BarMouseDown" MouseLeftButtonUp="BarMouseUp">
 11:                     <Grid.RowDefinitions>
 12:                         <RowDefinition Height="*" />
 13:                     </Grid.RowDefinitions>
 14:                     <Rectangle x:Name="rectangle" Opacity=".3" VerticalAlignment="Stretch">
 15:                         <Rectangle.Fill>
 16:                             <LinearGradientBrush EndPoint="1,1.2" StartPoint="1,0">
 17:                                 <GradientStop Color="LightBlue"/>
 18:                                 <GradientStop Color="Blue" Offset="1"/>
 19:                             </LinearGradientBrush>
 20:                         </Rectangle.Fill>
 21:                     </Rectangle>
 22:                 </Grid>
 23:             </Border>
 24:         </Grid>
 25:     </Canvas>

So that’s the layout.  In the code, the major actions we’ve got to handle are the moving the selector bar and the resizing of the selector bar. 

Let’s start with the resizing of the selector bar.  there are three events that are important here.  MouseDown, MouseUp, MouseMove. 

When the mouse button goes down, we want to start resizing if the mouse is currently in the white space to the right or left of the rectangle.

  1: 
  2:         void WindowMouseDown(object sender, MouseButtonEventArgs e)
  3:         {
  4:             if (ResizeEnabled)
  5:             {
  6:                 // Capture the mouse
  7:                 ((FrameworkElement)sender).CaptureMouse();
  8:                 // Store the start position
  9:                 _initialResizePoint = e.GetPosition(Canvas);
 10:                 _initialWindowSize.Width = window.ActualWidth;
 11:                 _initialWindowLocation.X = Canvas.GetLeft(window);
 12:                 // Set resizing to true
 13:                 _isResizing = true;
 14:             }
 15:         }

Now, as the mouse moves (before the mouse button goes up), we want to resize to the left or right depending on the side the mouse is currently on.

  1:         void WindowMouseMove(object sender, MouseEventArgs e)
  2:         {
  3:             if (ResizeEnabled)
  4:             {
  5:                 if (!_isResizing)
  6:                 {
  7:                     Point pos = e.GetPosition(window);
  8:                     if (pos.X <= HotSpotWidth)
  9:                     {
 10:                         window.Cursor = Cursors.SizeWE;
 11:                         _resizeAnchor = ResizeAnchor.Left;
 12:                     }
 13:                     else if (pos.X >= (window.ActualWidth - HotSpotWidth))
 14:                     {
 15:                         window.Cursor = Cursors.SizeWE;
 16:                         _resizeAnchor = ResizeAnchor.Right;
 17:                     }
 18:                     else
 19:                     {
 20:                         window.Cursor = null;
 21:                         _resizeAnchor = ResizeAnchor.None;
 22:                     }
 23:                 }
 24:                 else
 25:                 {
 26:                     Point position = e.GetPosition(Canvas);
 27:                     if (Canvas != null && position.X <= Canvas.ActualWidth && position.X >= 0)
 28:                     {
 29:                         double deltaX = position.X - _initialResizePoint.X;
 30: 
 31:                         switch (_resizeAnchor)
 32:                         {
 33:                             case ResizeAnchor.Left:
 34:                                 ResizeLeft(deltaX);
 35:                                 break;
 36:                             case ResizeAnchor.Right:
 37:                                 ResizeRight(deltaX);
 38:                                 break;
 39:                         }
 40:                     }
 41:                     if (SelectionChanged != null)
 42:                     {
 43:                         SelectionChanged(Left, Right, _resizeAnchor == ResizeAnchor.Right ? Direction.Right : Direction.Left);
 44:                     }
 45:                 }
 46:             }
 47:         }

 

  1: 
  2: 
  3:         private void ResizeRight(double deltaX)
  4:         {
  5:             //Right = deltaX;
  6:             window.Width = Math.Min(Width - (_initialWindowLocation.X), Math.Max(_initialWindowSize.Width + deltaX, MinWindowWidth));
  7:         }
  8: 
  9:         private void ResizeLeft(double deltaX)
 10:         {
 11:             if ((_initialWindowSize.Width - deltaX) > MinWindowWidth)
 12:             {
 13:                 // fix to avoid to move the window when we reached the minimal width resizing from the left
 14:                 double maxX = _initialWindowLocation.X + (_initialWindowSize.Width - MinWindowWidth);
 15:                 Canvas.SetLeft(window, Math.Min(_initialResizePoint.X + deltaX, maxX));
 16:                 if (_initialResizePoint.X + deltaX < maxX)
 17:                 {
 18:                     window.Width = _initialWindowSize.Width - deltaX;
 19:                 }
 20:                 _initialWindowLocation.X = _initialResizePoint.X + deltaX;
 21:             }
 22:         }

Finally, when the mouse button goes up, we want to stop resizing the selector

  1: 
  2:         void WindowMouseUp(object sender, MouseButtonEventArgs e)
  3:         {
  4:             if ((ResizeEnabled) && (_isResizing))
  5:             {
  6:                 // Release the mouse
  7:                 ((FrameworkElement)sender).ReleaseMouseCapture();
  8:                 // Set resizing to false
  9:                 _isResizing = false;
 10:                 if (SelectionFinishedChange != null)
 11:                 {
 12:                     SelectionFinishedChange(Left, Right, _resizeAnchor == ResizeAnchor.Left ? Direction.Left : Direction.Right);
 13:                 }
 14:             }
 15:         }

This is the basic functionality.  You can probably guess the implementation of the rest of the code but I’ll save you that effort and post the entire control as a silverlight project here. 

Download File - RegionSelector

You can expose the Left and Right (Width + Left) properties of this selector control to determine the selected positions on a higher level grid and thus determining the selected values of a range.

I hope that this saves you the trouble that I went through to figure out mouse capturing and resizing.


Posted in:   Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Rick Kierner posted on April 20, 2009 06:42

This weekend, I was fortunate enough to be selected to give a talk at Central Ohio Day Of .Net (CODODN).  The talk that was selected was “SharePoint _IS_ for Developers”  It was a 100-200 level talk about when/where a developer should get involved with a SharePoint installation.  The basic jest of my talk is that as developers and IT pros, we consistently don’t give users enough privilege when it comes to SharePoint.  As developers we should only get involved when we have to.  But when we have to get involved, this presentation talks about the integration points that SharePoint has given us and the power by which we can manipulate the data that is in SharePoint.

The slides don’t contain all the information that is in the presentation so I hope to get a screen cast out of the presentation soon.  You can get the slides here.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Rick Kierner posted on April 4, 2009 11:44

Last weekend, I tried something that turned out to be Gold.  We called it “Meet and Code.”  The premise is that we, as software development professionals, have an ultimate desire to improve on our “craft.”  Fundamentally, you could describe Meet and Code as “A group of developers got together and wrote some code with a common end result in mind.  Shortcuts were against the rule and deliberate practice of our craft was the primary goal.”  With this in mind, we had a couple of things in particular that we identified that get in the way of improving between 9 and 5.

Clients (Read: Users): everyone loves them since they pay the bills, they keep you employed.  The other thing they do is encourage  you to accomplish features quickly.  Unfortunately, this encourages you to fall back on the most comfortable practices you have realized to date.  Unfortunately, this is commonly not the best way to develop software. 

Lack of Communication: Quite commonly when we develop software, there is a lack of efficient, accurate communication between the developer and the project management.  There are several techniques that encourage good software development.  Identifying a publicly viewable list of features and monitoring progress throughout a project both lead to a more fulfilling development experience.

Meet and Code was conceived with these types of limitations in mind.  To avoid these limitations, we made sure that they were our primary focus throughout the event.  First, we decided that instead of delivering software, our goal was to learn how to deliver software the right way.  This creates a baseline to be able to fall back upon when times get tough in the future.  Secondly, we reduced the feedback loop by assigning a project manager for constant interaction throughout the project.

I like to measure success in a learning event by the number of “Ohhhhh, I get it now” statements made.  We had several and it was a great learning experience.  We focused much of our learning experience on TDD and Agile PM practices. 

The company I work for has an open developer space in the center of the office.  We setup shop in this area.  This allowed all of the developers to communicate freely with each other and conduct pair programming sessions when needed.

So, our goals for Meet and Code were met.  We didn’t finish all the tasks but we made some real headway with people who have never done TDD.  We are definitely going to do another phase to finish this application. 

In the theme of self improvement, we did a retrospective at the end of the weekend.  There were some things that really worked well with this effort.

  1. Common End Result:  We toyed with the idea of getting people together to just code together and solve random problems.  After some deliberation, we decided to come up with an application that had a variety of problems to solve and have everyone work toward that goal.  Our application for this round was an event management system.  We called it “EventHandler” because we’re nerdy.  The concept is similar to www.eventbrite.com but instead of a hosted service, it would be released as an open source software project.
  2. Geography:  Another debate we had was whether we would allow people to remote in/VPN in to work with us.  We decided that for true teamwork that we would be safer working together physically than remotely.  That worked out very well.  As a group together we were less likely to get distracted by environmental factors outside the office.
  3. 24-hr Access:  This is paramount.  when developers get in the zone, we often don’t want to stop.  Having a facility with 24 hr. access was key.
  4. Mentors:  This is something we did well and not well.  I operated as a mentor on technology moving from person to person to help with design decisions, TDD practices, etc.  We could have used another mentor for the number of people we had.  I think a 1:4 mentor:developer ratio would work best.

Of course, there are also things we would have improved; and will improve for the next phase.

  1. Part of the goal of the weekend was training.  Some people have never started an app from the ground up and never had to do the design part of a project.  For these people, they could have used a front-to-back of the design decision process.  I’m not sure what this would like but maybe a screencast/document.  This is debatable though.  I think that this speed bump is required for the learning process.
  2. Create dev environment image to use.  This would have been nice since practically no one showed up with ASP.Net MVC, VS 2008 SP1, and Team Explorer on their machines.
  3. Create the automated build server ahead of time.  This task is practically just busy work and it kept a couple people busy for 4 hours or so.  That’s precious dev time when you only have a weekend of coding time.

This was a fantastic event.  The thing I liked about it was that it was a “Do” event.  We did stuff.  After talking about software as much as I do, it’s nice to actually accomplish something.


Posted in:   Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

I ran into a situation today where I had an access database that had to export its data to an excel spreadsheet.  The excel spreadsheet was formatted to the customer’s liking and I basically needed to automate the action of copy/paste from an access table (or query) to excel.  I was able to do some googling and found the answer as an aggregate of several forum posts.  I didn’t however find the answer explicitly so I’m posting what I found here.

   1: 'Assumes that an excel spreadsheet exists.  For this example, it's already got one sheet named "MyData".
   2: 'There's text in the cell C4
   3:  
   4: DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "tbl_employees", "C:\Temp\Test.xls", True
   5: DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "tbl_vendor_contact_hist", "c:\Temp\Test.xls", True
   6:  
   7: 'An excel spreadsheet exists and now has 3 sheets ("MyData", "tbl_employees", "tbl_vendor_contact")
   8: 'Now we need to create an Excel Application object
   9: Dim xls As Excel.Application
  10: Set xls = CreateObject("excel.application")
  11: 'Now we open the file we edited above
  12: xls.Workbooks.Open ("C:\Temp\Test.xls")
  13:  
  14: 'Next we select the sheet that was there originally because we want to insert lines above
  15: 'the pre-existing text for no reason other than this was difficult to figure out and I want
  16: 'to show you how
  17: xls.Sheets("MyData").Select
  18: xls.Range("A1").Select
  19: xls.ActiveSheet.Range("C4").Insert xlDown
  20:  
  21: 'Now we have to choose the first /new/ sheet and copy data in that tab
  22: xls.Sheets("tbl_employees").Select
  23: xls.Range("A1", "B4").Select
  24: xls.Selection.Copy
  25:  
  26: 'Finally we reselect the original sheet and past the information above the pre-existing text
  27: xls.Sheets("MyData").Select
  28: xls.Range("A1").Select
  29: xls.ActiveSheet.Paste
  30:  
  31: 'Always save, close and quit
  32: xls.ActiveWorkbook.save
  33: xls.ActiveWorkbook.Close
  34: xls.Quit
  35: Set xls = Nothing
I hope this saves someone some time down the road. 

Posted in:   Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Central Ohio Day of .Net

WM .Net University April 4, 2009 - I'll be there!

Search Blog

Recent Posts

Blog Roll

Hide Blog Roll

OPMLDownload OPML file
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009 Rick.Brain.Flush()