Rick Kierner posted on January 4, 2010 07:17

I was tagged by Jeremiah Peschka in his post about 2010 goals.  So here’s my response.

I am a huge fan of goals.  In my opinion if you don’t have a roadmap of where you want to go, there’s zero chance that you will end up anywhere near there.  Goals are huge; they’re important; they’re critical to success.  If you don’t have success, you have reached some degree of failure.  And no one likes to be a failure.  And they are VERY hard to create.  There are several things that go into creating good goals.  Lucky for you, I’ve created a 3-step process to help anyone create good goals.

1.) Plan

First, a long term plan is necessary before identifying annual goals.  The term “long-term” is relative.  I refuse to plan any further back professionally than I have professional history.  So if I’ve been working for about 10 years, there’s no way to have a realistic 20 year plan.  Quite often, it’s not realistic to have a valid 10 year plan.  But in my case, I think it is possible. 

In ten years, I want to be a noteworthy developer, leader, mentor, and manager in Central Ohio.  I want to be someone that people look to for career, professional, and technical guidance. 

Note a few attributes about my “long-term” plan.  There’s nothing that is measureable, a few things are quite subjective.  That’s because it’s my plan.  I have definitions of terms like “noteworthy” and “that people look to” in my head.  And that’s good enough.  My plan in particular is very soft.  When I was 1 year out of school, my one-year plan sounded more like “I want to be a good programmer and provide a value-added skill set to the project I’m on.”  So I’ve gotten softer; I feel like my skill set has developed into that of a mentor, leader, and organizer.  This is the most rewarding work I do on a day-to-day basis.  I did intentionally leave “developer” in my plan because I write code, I do it well, I do it fast.  But I work with a bunch of developers.  Lots of people write code well and fast.  I demand a lot of myself and one of those things is to be unique (noteworthy).  So because of that, I don’t *just* code.  I offer a unique multiplier to projects with my softer skills.

2.) Quantify

Goals should have measurable outcomes.  These are completely different from plans.  Goals have a definitive pass/fail quantifier.  Some things are easy to quantify.  Previous goals I’ve had are “Earn Certification XYZ by June 200X”.  If I earn that specific certification by June of 200X, then I have attained my goal.  If don’t earn it or earn it after June, I am a failure.  There’s no gray area here.  You are successful or a failure.  That may be harsh but as soon as we get wishy washy on our definitions of success or failure, you end up with meaningless goals, no destination, and ultimately a wasted effort. 

Here are my goals for 2010:

  • Read 6 books that are oriented to professional or technical development by December 31, 2010
  • Create an LLC to be a parent to potential side projects by March 1, 2010
  • Continue my 3 mentee relationships and meet with each person at least once per month during 2010
  • Create at least 1 online system that is built to provide a continuous revolving income stream to subsidize my personal income

And there you have it.  4 measurable goals.  I’ll break them down to highlight the effort I put into the wording of my goals and to explain them in more detail.

Reading

I enjoy reading.  I think that reading provides an excellent way to improve one’s self.  I intend to once again read 6 books.  I have a few in mind but don’t want to limit my self to those in case a better one pops up.  I don’t change my goals.  These will signify my success for the 2010 calendar year.

LLC

Over the past 3-4 years, I’ve had several ideas for small companies or services that require little to no maintenance or attention.  Sometimes, these ideas would have produced a little bit of money and therefore would have required some type of business to own them.  But because I am was a chicken, I’ve never created the LLC and therefore never followed through with my ideas.  This year, I’ll create an LLC to host systems  or services I have ideas about.

Mentoring

Mentoring is AWESOME.  Helping people become more by providing guidance, leadership, education, and opportunities has been the most fun I’ve had in my professional career.  I love doing it and I have recently established 3 relationships with people in that capacity.  I want to continue this effort but “continue” isn’t quantifiable.  I want to meet each month to make sure that progress is made… A meeting is quantifiable.

Online Service

This one is related to the LLC goal.  I am currently working on a nice piece of software that will provide an interesting service.  I fully expect to be able to release a production quality instance by May.  I am hoping that creating one service will lead to additional ones.

3.) Measure

Throughout the year, these goals should be checked for status.  This will create a motivational element throughout the year and remind you that you should be working hard to accomplish your goals and not be a failure.  To be more specific, I like to keep a spreadsheet on my desktop that identifies the goals for the year and a list of achievements that are related and not related to those goals.  This helps me keep track of how I’m doing and whether I can regard this year as a successful year.  Additionally, it helps me provide the necessary information to my employer for my annual review.  I tend to incorporate my goals into my company’s annual review process but I could certainly see that effort as optional. 

Notes:

I also create personal goals.  I’ve chosen not to share them in this venue.  If you’re interested in talking about personal goals, hit me up via email or IM and I can share my unique view on personal goal setting as well

Conclusion

You now have 3 easy steps, some examples and some explanations.  Get to work, become better at whatever you want to become better at.


Posted in:   Tags:
Rick Kierner posted on November 18, 2009 22:25

I’ll be attending CodeMash early next year.  Not only that but my AWESOME employer, HMB, is sending a total of 10 people to make sure that we can capitalize on the fantastic content that comes out of CodeMash each year.  I'll be the one on the lazy river with my laptopTo further emphasize the role that this conference plays on HMB, HMB has 48 employees.  That means that over 20% of our staff is being offered the opportunity to attend at no cost to the attendee.

If you’re interested in attending CodeMash, I recommend that you register early.  This conference has a strong tradition of selling out.  The speakers at this conference in particular are typically the best of breed for the given technology they are speaking on. 

For information more than

CodeMash is a unique event that will educate developers on current practices, methodologies, and technology trends in a variety of platforms and development languages such as Java, .Net, Ruby, Python and PHP.

make sure you visit the CodeMash website. 

I can also personally vouch for the PreCompiler even that happens the day prior to the conference.  The PreCompiler is that part of a conference that everyone says “would have been cool if they had done …”  Basically, some excellent teachers, subject matter experts, and technologists have volunteered their time to *show* you how they do best practices or develop software in a particular language/technology. There will be hands on sessions on TDD/BDD, Ruby, Coaching, the Software Craftsmanship, and a whole lot of other topics.  I like to think of these sessions as “The best showing how they do what they do best”  I recommend trying it out.

CodeMash is held at the Kalahari Resort in Sandusky, OH on Jan 13-15. 


Posted in:   Tags: ,
Rick Kierner posted on November 6, 2009 06:15

I’ve been working through a few UI related requests on my current project.  One such request is to alter the appearance of the WPF TabControl to have a single row of tabs.  The default behavior is to wrap the tabs beyond the single line as space is needed.

This is the default behavior

image

I’d like mine to look more like this:

image

So it may have taken a little while to figure it out…but now I know…and I will share with the world.

The first thing you need to do is have an empty window and add a TabControl to it.

   1: <Window
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     x:Class="WpfApplication2.TabWindow"
   5:     x:Name="Window"
   6:     Title="TabWindow"
   7:     Width="640" Height="480"> 
   8:  
   9:     <Grid x:Name="LayoutRoot">
  10:         <TabControl>
  11:             <TabItem Header="TabItem">
  12:                 <Grid/>
  13:             </TabItem>
  14:             <TabItem Header="TabItem">
  15:                 <Grid/>
  16:             </TabItem>
  17:         </TabControl>
  18:     </Grid>
  19: </Window>

Next you need to edit the template for the TabControl.  To do this in Blend 3, select the TabControl and expand the Miscellaneous section on the properties window.  Toward the bottom, there will be an property for Template.  Click in the little square box beside the entry field for template and select “convert to new resource”.  This will open a dialog window for the location you’d like to place the new template resource.  I just chose the same document.  I named the template “ScrollableTabControlTemplate” 

This will create a section of XAML in your window that specifies the appearance of the TabControl.  To be able to edit this new resource, you have to once again click on that box next to template and this time select “Edit Resource”.  This will change the designer to focus on the TabControl Template that you are working with.  Note that the root of the elements in the Objects and Timelines window is the ControlTemplate now instead of Window.  When you break it down, the TabControl is a Grid that has 2 columns, 2 rows, a TabPanel, and a border that contains the content.

   1: <ControlTemplate x:Key="ScrollableTabControlTemplate" TargetType="{x:Type TabControl}">
   2:             <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
   3:                 <Grid.ColumnDefinitions>
   4:                     <ColumnDefinition x:Name="ColumnDefinition0"/>
   5:                     <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
   6:                 </Grid.ColumnDefinitions>
   7:                 <Grid.RowDefinitions>
   8:                     <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
   9:                     <RowDefinition x:Name="RowDefinition1" Height="*"/>
  10:                 </Grid.RowDefinitions>
  11:                 <TabPanel x:Name="HeaderPanel" Margin="2,2,2,0" IsItemsHost="True" Panel.ZIndex="1" Grid.Column="0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/>
  12:                 <Border x:Name="ContentPanel" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
  13:                     <ContentPresenter x:Name="PART_SelectedContentHost" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectedContent}" ContentSource="SelectedContent" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentTemplate="{TemplateBinding SelectedContentTemplate}"/>
  14:                 </Border>
  15:             </Grid>
  16:             <ControlTemplate.Triggers>
  17:                 <Trigger Property="TabStripPlacement" Value="Bottom">
  18:                     <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
  19:                     <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
  20:                     <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
  21:                     <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
  22:                     <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
  23:                 </Trigger>
  24:                 <Trigger Property="TabStripPlacement" Value="Left">
  25:                     <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
  26:                     <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
  27:                     <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
  28:                     <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
  29:                     <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
  30:                     <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
  31:                     <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
  32:                     <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
  33:                     <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
  34:                 </Trigger>
  35:                 <Trigger Property="TabStripPlacement" Value="Right">
  36:                     <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
  37:                     <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
  38:                     <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
  39:                     <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
  40:                     <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
  41:                     <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
  42:                     <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
  43:                     <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
  44:                     <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
  45:                 </Trigger>
  46:                 <Trigger Property="IsEnabled" Value="False">
  47:                     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
  48:                 </Trigger>
  49:             </ControlTemplate.Triggers>
  50:         </ControlTemplate>
  51:  
  52: I zeroed in on the TabPanel.  (Line XX above) This is where the tabs exist.  So in order to be able to put them in a single row, I simply wrapped the TabPanel with a ScrollViewer control.  I set the vertical scroll bar to disabled and the horizontal scrollbar to Auto.  
  53:  
  54: <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
  55:                 <Grid.ColumnDefinitions>
  56:                     <ColumnDefinition x:Name="ColumnDefinition0"/>
  57:                     <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
  58:                 </Grid.ColumnDefinitions>
  59:                 <Grid.RowDefinitions>
  60:                     <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
  61:                     <RowDefinition x:Name="RowDefinition1" Height="*"/>
  62:                 </Grid.RowDefinitions>
  63:                 <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
  64:                     <TabPanel x:Name="HeaderPanel" Margin="2,2,2,0" IsItemsHost="True" Panel.ZIndex="1" Grid.Column="0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/>
  65:                 </ScrollViewer>
  66:                 <Border x:Name="ContentPanel" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
  67:                     <ContentPresenter x:Name="PART_SelectedContentHost" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectedContent}" ContentSource="SelectedContent" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentTemplate="{TemplateBinding SelectedContentTemplate}"/>
  68:                 </Border>
  69:             </Grid>
  70:  
  71: Now that will give us a pretty ugly horizontal scrollbar if we run the application.  We don’t like ugly so now we have to change the template for that ScrollViewer.  Follow the steps that we did for the TabControl Template and create a new resource for the ScrollViewer.  I named mine “ScrollViewerTemplate”.  Now I once again drilled down into the new template I created by selecting “Edit Resource” from the properties window.  
  72:  
  73: <ControlTemplate x:Key="ScrollViewerTemplate" TargetType="{x:Type ScrollViewer}">
  74:             <Grid x:Name="Grid" Background="{TemplateBinding Background}">
  75:                 <Grid.ColumnDefinitions>
  76:                     <ColumnDefinition Width="*"/>
  77:                     <ColumnDefinition Width="Auto"/>
  78:                 </Grid.ColumnDefinitions>
  79:                 <Grid.RowDefinitions>
  80:                     <RowDefinition Height="*"/>
  81:                     <RowDefinition Height="Auto"/>
  82:                 </Grid.RowDefinitions>
  83:                 <Rectangle x:Name="Corner" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Column="1" Grid.Row="1"/>
  84:                 <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.Column="0" Grid.Row="0" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False"/>
  85:                 <ScrollBar x:Name="PART_VerticalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="1" Grid.Row="0" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" AutomationProperties.AutomationId="VerticalScrollBar"/>
  86:                 <ScrollBar x:Name="PART_HorizontalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="0" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" AutomationProperties.AutomationId="HorizontalScrollBar"/>
  87:             </Grid>
  88:         </ControlTemplate>
  89:  

As you can see, several controls exist in this template.  There’s a rectangle, a content presenter and two scrollbars.  I know I’m not going to need the vertical scrollbar, so I deleted it.  If you run your application now, you’ll actually see the horizontal scrollbar.  This is still a bit ugly.  As I’ve said before, we don’t like ugly.

image

So to get rid of this, we need to change the template for the horizontal scrollbar.  Before we do that though, let’s look at how the scrollbar exists in relation to the content.  If you notice there is a grid in this ScrollViewerTemplate.  It has two rows.  We don’t want two rows, we want one row with the left button on the left, the right button on the right and all the tabs in between.  Ok, so let’s delete the second row, put the horizontal scroll bar in the first row and then indent the ScrollContentPresenter by changing the margin.  Now this is important.  If we leave the scrollbar declared below the ScrollContentPresenter in the XAML, then when this renders, the scrollbar will be in front of the tabs because they are in the same row of the grid now.  This is unacceptable, so we have to move the declaration of the scrollbar to above the ScrollContentPresenter

   1: <ControlTemplate x:Key="ScrollViewerTemplate" TargetType="{x:Type ScrollViewer}">
   2:     <Grid x:Name="Grid" Background="{TemplateBinding Background}">
   3:         <Grid.ColumnDefinitions>
   4:             <ColumnDefinition Width="*"/>
   5:             <ColumnDefinition Width="Auto"/>
   6:         </Grid.ColumnDefinitions>
   7:         <Grid.RowDefinitions>
   8:             <RowDefinition Height="*"/>
   9:         </Grid.RowDefinitions>
  10:         <Rectangle x:Name="Corner" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Column="1" Grid.Row="1"/>
  11:         <ScrollBar x:Name="PART_HorizontalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="0" Grid.Row="0" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" AutomationProperties.AutomationId="HorizontalScrollBar"/>
  12:         <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Margin="15,2,15,0" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.Column="0" Grid.Row="0" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False"/>                
  13:     </Grid>
  14: </ControlTemplate>

So here we are.  we have a scrollbar that is behind our tabs and only looks a little funny

image

Let’s finish this up by changing the template for the horizontal scroll bar.  This is done the same way we did the other two templates. We’ll get this by default:

   1: <ControlTemplate x:Key="HorizontalScrollBarTemplate" TargetType="{x:Type ScrollBar}">
   2:             <Grid x:Name="Bg" SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
   3:                 <Grid.ColumnDefinitions>
   4:                     <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
   5:                     <ColumnDefinition Width="1E-05*"/>
   6:                     <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
   7:                 </Grid.ColumnDefinitions>
   8:                 <RepeatButton IsEnabled="{TemplateBinding IsMouseOver}" Command="ScrollBar.LineLeftCommand" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="LeftArrow">
   9:                     <RepeatButton.Style>
  10:                         <Style TargetType="{x:Type RepeatButton}">
  11:                             <Setter Property="OverridesDefaultStyle" Value="True"/>
  12:                             <Setter Property="Focusable" Value="False"/>
  13:                             <Setter Property="IsTabStop" Value="False"/>
  14:                             <Setter Property="Template">
  15:                                 <Setter.Value>
  16:                                     <ControlTemplate TargetType="{x:Type RepeatButton}">
  17:                                         <Microsoft_Windows_Themes:ScrollChrome x:Name="Chrome" SnapsToDevicePixels="True" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="{TemplateBinding Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph}"/>
  18:                                     </ControlTemplate>
  19:                                 </Setter.Value>
  20:                             </Setter>
  21:                         </Style>
  22:                     </RepeatButton.Style>
  23:                 </RepeatButton>
  24:                 <Track x:Name="PART_Track" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Column="1">
  25:                     <Track.DecreaseRepeatButton>
  26:                         <RepeatButton Command="ScrollBar.PageLeftCommand">
  27:                             <RepeatButton.Style>
  28:                                 <Style TargetType="{x:Type RepeatButton}">
  29:                                     <Setter Property="OverridesDefaultStyle" Value="True"/>
  30:                                     <Setter Property="Background" Value="Transparent"/>
  31:                                     <Setter Property="Focusable" Value="False"/>
  32:                                     <Setter Property="IsTabStop" Value="False"/>
  33:                                     <Setter Property="Template">
  34:                                         <Setter.Value>
  35:                                             <ControlTemplate TargetType="{x:Type RepeatButton}">
  36:                                                 <Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
  37:                                             </ControlTemplate>
  38:                                         </Setter.Value>
  39:                                     </Setter>
  40:                                 </Style>
  41:                             </RepeatButton.Style>
  42:                         </RepeatButton>
  43:                     </Track.DecreaseRepeatButton>
  44:                     <Track.IncreaseRepeatButton>
  45:                         <RepeatButton Command="ScrollBar.PageRightCommand">
  46:                             <RepeatButton.Style>
  47:                                 <Style TargetType="{x:Type RepeatButton}">
  48:                                     <Setter Property="OverridesDefaultStyle" Value="True"/>
  49:                                     <Setter Property="Background" Value="Transparent"/>
  50:                                     <Setter Property="Focusable" Value="False"/>
  51:                                     <Setter Property="IsTabStop" Value="False"/>
  52:                                     <Setter Property="Template">
  53:                                         <Setter.Value>
  54:                                             <ControlTemplate TargetType="{x:Type RepeatButton}">
  55:                                                 <Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
  56:                                             </ControlTemplate>
  57:                                         </Setter.Value>
  58:                                     </Setter>
  59:                                 </Style>
  60:                             </RepeatButton.Style>
  61:                         </RepeatButton>
  62:                     </Track.IncreaseRepeatButton>
  63:                     <Track.Thumb>
  64:                         <Thumb Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="HorizontalGripper">
  65:                             <Thumb.Style>
  66:                                 <Style TargetType="{x:Type Thumb}">
  67:                                     <Setter Property="OverridesDefaultStyle" Value="True"/>
  68:                                     <Setter Property="IsTabStop" Value="False"/>
  69:                                     <Setter Property="Template">
  70:                                         <Setter.Value>
  71:                                             <ControlTemplate TargetType="{x:Type Thumb}">
  72:                                                 <Microsoft_Windows_Themes:ScrollChrome x:Name="Chrome" SnapsToDevicePixels="True" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsDragging}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="{TemplateBinding Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph}"/>
  73:                                             </ControlTemplate>
  74:                                         </Setter.Value>
  75:                                     </Setter>
  76:                                 </Style>
  77:                             </Thumb.Style>
  78:                         </Thumb>
  79:                     </Track.Thumb>
  80:                 </Track>
  81:                 <RepeatButton IsEnabled="{TemplateBinding IsMouseOver}" Command="ScrollBar.LineRightCommand" Grid.Column="2" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="RightArrow">
  82:                     <RepeatButton.Style>
  83:                         <Style TargetType="{x:Type RepeatButton}">
  84:                             <Setter Property="OverridesDefaultStyle" Value="True"/>
  85:                             <Setter Property="Focusable" Value="False"/>
  86:                             <Setter Property="IsTabStop" Value="False"/>
  87:                             <Setter Property="Template">
  88:                                 <Setter.Value>
  89:                                     <ControlTemplate TargetType="{x:Type RepeatButton}">
  90:                                         <Microsoft_Windows_Themes:ScrollChrome x:Name="Chrome" SnapsToDevicePixels="True" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="{TemplateBinding Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph}"/>
  91:                                     </ControlTemplate>
  92:                                 </Setter.Value>
  93:                             </Setter>
  94:                         </Style>
  95:                     </RepeatButton.Style>
  96:                 </RepeatButton>
  97:             </Grid>
  98:             <ControlTemplate.Triggers>
  99:                 <Trigger Property="IsEnabled" Value="False">
 100:                     <Setter Property="Background" TargetName="Bg" Value="#FFF4F4F4"/>
 101:                 </Trigger>
 102:             </ControlTemplate.Triggers>
 103:         </ControlTemplate>
It’s big, and we don’t need a lot of it.  The first thing I did was get rid of the “PART_Track” in the middle.  We won’t see that part anyway.   Next, I changed the commands of both of the RepeatButtons.  The one on the left should be “ScrollBar.PageLeftCommand” and the one on the right should be “ScrollBar.PageRightCommand”  I decided to use Page Right/Left because the moving by line wasn’t fast enough.

The next thing I did was completely change the way the RepeatButtons look.  I did this by taking out the “Microsoft_Windows_Themes:ScrollCrhome” control and replacing it with a Border and Path control.  We can more intimately control the colors and design this way.  Next I gave the parent Grid control a static “Black” background.

   1: <ControlTemplate x:Key="HorizontalScrollBarTemplate" TargetType="{x:Type ScrollBar}">
   2:     <Grid x:Name="Bg" SnapsToDevicePixels="True" Background="Black">
   3:         <Grid.ColumnDefinitions>
   4:             <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
   5:             <ColumnDefinition Width="1E-05*"/>
   6:             <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
   7:         </Grid.ColumnDefinitions>
   8:         <RepeatButton IsEnabled="{TemplateBinding IsMouseOver}" Command="ScrollBar.PageLeftCommand" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="LeftArrow">
   9:             <RepeatButton.Style>
  10:                 <Style TargetType="{x:Type RepeatButton}">
  11:                     <Setter Property="OverridesDefaultStyle" Value="True"/>
  12:                     <Setter Property="Focusable" Value="False"/>
  13:                     <Setter Property="IsTabStop" Value="False"/>
  14:                     <Setter Property="Template">
  15:                         <Setter.Value>
  16:                             <ControlTemplate TargetType="{x:Type RepeatButton}">
  17:                                 <Border Background="{x:Null}" Height="18" Width="18" >
  18:                                     <Path Data=" M 8 15 L 8 3 L 2 9 Z" Fill="White" />
  19:                                 </Border>
  20:                             </ControlTemplate>
  21:                         </Setter.Value>
  22:                     </Setter>
  23:                 </Style>
  24:             </RepeatButton.Style>
  25:         </RepeatButton>
  26:         <RepeatButton IsEnabled="{TemplateBinding IsMouseOver}" Command="ScrollBar.PageRightCommand" Grid.Column="2" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="RightArrow">
  27:             <RepeatButton.Style>
  28:                 <Style TargetType="{x:Type RepeatButton}">
  29:                     <Setter Property="OverridesDefaultStyle" Value="True"/>
  30:                     <Setter Property="Focusable" Value="False"/>
  31:                     <Setter Property="IsTabStop" Value="False"/>
  32:                     <Setter Property="Template">
  33:                         <Setter.Value>
  34:                             <ControlTemplate TargetType="{x:Type RepeatButton}">
  35:                                 <Border Background="{x:Null}" Height="18" Width="18" >
  36:                                     <Path Data=" M 9 15 L 9 3 L 15 9 Z" Fill="White" />
  37:                                 </Border>
  38:                             </ControlTemplate>
  39:                         </Setter.Value>
  40:                     </Setter>
  41:                 </Style>
  42:             </RepeatButton.Style>
  43:         </RepeatButton>
  44:     </Grid>
  45:     <ControlTemplate.Triggers>
  46:         <Trigger Property="IsEnabled" Value="False">
  47:             <Setter Property="Background" TargetName="Bg" Value="#FFF4F4F4"/>
  48:         </Trigger>
  49:     </ControlTemplate.Triggers>
  50: </ControlTemplate>

That’s all I had to do.  I ended up with the following design.  The buttons work, I don’t have multiple rows of tabs.  I’m a happy camper.  There are a ton of other design opportunities.  This was just a quick one that was fairly easy to demonstrate.

image


Posted in:   Tags:

Jim Holmes and a few local technology leaders are organizing a one-day, free event to evangelize building the basics of software development.  These are skills that every developer should have.  If you can make it to this event, please do.  For details check Jim’s blog post


Posted in:   Tags:
Rick Kierner posted on August 20, 2009 04:37

A friend and coworker of mine has a blog.  He focuses mainly on Silverlight right now.  I would certainly recommend checking his posts out about a custom timeline visualization control that he created.

Jose’s blog is located: http://codeforward.blogspot.com/


Posted in:   Tags:
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010 Rick.Brain.Flush()