<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Comment Feed for Channel 9 - New Custom Slider for Silverlight 2 media players</title>
	<atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Blogs/benwagg/New-Custom-Slider-for-Silverlight-2-media-players/RSS"></atom:link>
	<image>
		<url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
		<title>Channel 9 - New Custom Slider for Silverlight 2 media players</title>
		<link></link>
	</image>
	<description> My Silverlight teammates Akshay Johar and Andre Michaud have built a new custom slider for use in Silverlight 2 media players. When you scrub the default slider in a MediaElement today, it generates a whole slew of valueChanged events, resulting in a huge number of seeks per second. This can confuse media playback, particularly when streaming from Windows Media Services, which then gets flooded with many requests a second. Essentially it detects a “crazy mode” scrub, and quietly ignores it while the “crazy mode” is in place. Once out of this mode, it happily sends and receives a successful seek. So, the player only fires ValueChanged on mouse up (on the slider thumb or the slider tracker), or the final seek request of a cluster that comes in at once. It’s also uses Tim Heuer’s absolute value slider. Now, let me try this new Windows Live Writer plug-in for Insert Code Snippet for the C# code.(EDIT) A sample project is also now available for download.  1: using System; 2: using System.Net; 3: using System.Windows; 4: using System.Windows.Controls; 5: using System.Windows.Documents; 6: using System.Windows.Ink; 7: using System.Windows.Input; 8: using System.Windows.Media; 9: using System.Windows.Media.Animation; 10: using System.Windows.Shapes; 11: using System.Windows.Controls.Primitives; 12: using System.Windows.Threading; 13:&amp;nbsp;  14: namespace VirtualizedSlider 15: { 16:     public class CustomSlider : Slider 17:     { 18:         public Thumb horizontalThumb; 19:         private FrameworkElement horizontalLeftTrack; 20:         private FrameworkElement horizontalRightTrack; 21:         private double oldValue = 0, newValue = 0, prevNewValue = 0; 22:         public event RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt; MyValueChanged; 23:         public event RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt; MyValueChangedInDrag; 24:          25:         private DispatcherTimer dragtimer = new DispatcherTimer(); 26:         private double dragTimeElapsed = 0; 27:         private const short DragWaitThreshold = 200, DragWaitInterval = 100; 28:         public Rectangle progressRect = null; 29:         private bool dragSeekJustFired = false; 30:&amp;nbsp;  31:         public CustomSlider() 32:         { 33:             this.ValueChanged &amp;#43;= new RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt;(CustomSlider_ValueChanged); 34:             dragtimer.Interval = new TimeSpan(0, 0, 0, 0, DragWaitInterval); 35:             dragtimer.Tick &amp;#43;= new EventHandler(dragtimer_Tick); 36:              37:         } 38:&amp;nbsp;  39:         void dragtimer_Tick(object sender, EventArgs e) 40:         { 41:             dragTimeElapsed &amp;#43;= DragWaitInterval; 42:             if (dragTimeElapsed &amp;gt;= DragWaitThreshold) 43:             { 44:                 RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt; handler = MyValueChangedInDrag; 45:                 if ((handler != null) &amp;amp;&amp;amp; (newValue != prevNewValue)) 46:                 { 47:                     handler(this, new RoutedPropertyChangedEventArgs&amp;lt;double&amp;gt;(oldValue, newValue)); 48:                     dragSeekJustFired = true; 49:                     prevNewValue = newValue; 50:                 } 51:                 dragTimeElapsed = 0; 52:             } 53:         } 54:&amp;nbsp;  55:         void CustomSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs&amp;lt;double&amp;gt; e) 56:         { 57:             oldValue = e.OldValue; 58:             newValue = e.NewValue; 59:             if (horizontalThumb.IsDragging) 60:             { 61:                 dragTimeElapsed = 0; 62:                 dragtimer.Stop(); 63:                 dragtimer.Start(); 64:                 dragSeekJustFired = false; 65:             } 66:         } 67:&amp;nbsp;  68:         public override void OnApplyTemplate() 69:         { 70:             base.OnApplyTemplate(); 71:&amp;nbsp;  72:             horizontalThumb = GetTemplateChild(&amp;quot;HorizontalThumb&amp;quot;) as Thumb; 73:&amp;nbsp;  74:             horizontalLeftTrack = GetTemplateChild(&amp;quot;LeftTrack&amp;quot;) as FrameworkElement; 75:             horizontalRightTrack = GetTemplateChild(&amp;quot;RightTrack&amp;quot;) as FrameworkElement; 76:             progressRect = GetTemplateChild(&amp;quot;progressRect&amp;quot;) as Rectangle; 77:&amp;nbsp;  78:             if (horizontalLeftTrack != null) horizontalLeftTrack.MouseLeftButtonDown &amp;#43;= new MouseButtonEventHandler(OnMoveThumbToMouse); 79:             if (horizontalRightTrack != null) horizontalRightTrack.MouseLeftButtonDown &amp;#43;= new MouseButtonEventHandler(OnMoveThumbToMouse); 80:&amp;nbsp;  81:             horizontalThumb.DragCompleted &amp;#43;= new DragCompletedEventHandler(DragCompleted); 82:             progressRect.Width = this.Width;             83:         } 84:&amp;nbsp;  85:         private void OnMoveThumbToMouse(object sender, MouseButtonEventArgs e) 86:         { 87:             e.Handled = true; 88:             Point p = e.GetPosition(this); 89:&amp;nbsp;  90:             if (this.Orientation == Orientation.Horizontal) 91:             { 92:                 Value = (p.X - (horizontalThumb.ActualWidth / 2)) / (ActualWidth - horizontalThumb.ActualWidth) * Maximum; 93:             } 94:             RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt; handler = MyValueChanged; 95:             if (handler != null) 96:             { 97:                 handler(this, new RoutedPropertyChangedEventArgs&amp;lt;double&amp;gt;(oldValue, Value)); 98:             } 99:         } 100:&amp;nbsp;  101:         private void DragCompleted(object sender, DragCompletedEventArgs e) 102:         { 103:             dragtimer.Stop(); 104:             dragTimeElapsed = 0; 105:             RoutedPropertyChangedEventHandler&amp;lt;double&amp;gt; handler = MyValueChanged; 106:             if ((handler != null) &amp;amp;&amp;amp; (!dragSeekJustFired)) 107:             { 108:                 handler(this, new RoutedPropertyChangedEventArgs&amp;lt;double&amp;gt;(oldValue, this.Value)); 109:             } 110:         } 111:     } 112: }&amp;nbsp; And here’s the XAML from the progressSliderStyle, demonstrating how the custom slider knows about mouse clicks on the track (the “LeftTrack” and “RightTrack” rectangles inserted in the template handle this):  1: &amp;lt;Setter Property=&amp;quot;Template&amp;quot;&amp;gt; 2:                  &amp;lt;Setter.Value&amp;gt; 3:                      &amp;lt;ControlTemplate TargetType=&amp;quot;Slider&amp;quot;&amp;gt; 4:                          &amp;lt;Grid x:Name=&amp;quot;Root&amp;quot;&amp;gt; 5:                              &amp;lt;Grid.Resources&amp;gt; 6:                                  &amp;lt;ControlTemplate x:Key=&amp;quot;RepeatButtonTemplate&amp;quot;&amp;gt; 7:                                      &amp;lt;Grid x:Name=&amp;quot;Root&amp;quot; Opacity=&amp;quot;0&amp;quot; Background=&amp;quot;Transparent&amp;quot;/&amp;gt; 8:                                  &amp;lt;/ControlTemplate&amp;gt; 9:                              &amp;lt;/Grid.Resources&amp;gt; 10:                              &amp;lt;vsm:VisualStateManager.VisualStateGroups&amp;gt; 11:                                  &amp;lt;vsm:VisualStateGroup x:Name=&amp;quot;CommonStates&amp;quot;&amp;gt; 12:                                      &amp;lt;vsm:VisualState x:Name=&amp;quot;Normal&amp;quot;/&amp;gt; 13:                                      &amp;lt;vsm:VisualState x:Name=&amp;quot;MouseOver&amp;quot;/&amp;gt; 14:                                      &amp;lt;vsm:VisualState x:Name=&amp;quot;Disabled&amp;quot;&amp;gt; 15:                                          &amp;lt;Storyboard&amp;gt; 16:                                              &amp;lt;DoubleAnimation Storyboard.TargetName=&amp;quot;Root&amp;quot; Storyboard.TargetProperty=&amp;quot;(UIElement.Opacity)&amp;quot; To=&amp;quot;0.5&amp;quot;/&amp;gt; 17:                                          &amp;lt;/Storyboard&amp;gt; 18:                                      &amp;lt;/vsm:VisualState&amp;gt; 19:                                  &amp;lt;/vsm:VisualStateGroup&amp;gt; 20:                              &amp;lt;/vsm:VisualStateManager.VisualStateGroups&amp;gt; 21:&amp;nbsp;  22:                              &amp;lt;!-- Horizontal Template --&amp;gt; 23:                              &amp;lt;Grid x:Name=&amp;quot;HorizontalTemplate&amp;quot; Background=&amp;quot;{TemplateBinding Background}&amp;quot;&amp;gt; 24:                                  &amp;lt;Grid.ColumnDefinitions&amp;gt; 25:                                      &amp;lt;ColumnDefinition Width=&amp;quot;Auto&amp;quot;/&amp;gt; 26:                                      &amp;lt;ColumnDefinition Width=&amp;quot;Auto&amp;quot;/&amp;gt; 27:                                      &amp;lt;ColumnDefinition Width=&amp;quot;*&amp;quot;/&amp;gt; 28:                                  &amp;lt;/Grid.ColumnDefinitions&amp;gt; 29:&amp;nbsp;  30:                                  &amp;lt;!-- Track Layer --&amp;gt; 31:                                  &amp;lt;Rectangle x:Name=&amp;quot;progressRect&amp;quot; Stroke=&amp;quot;#FFA3AEB9&amp;quot; StrokeThickness=&amp;quot;{TemplateBinding BorderThickness}&amp;quot; Fill=&amp;quot;Red&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Grid.ColumnSpan=&amp;quot;3&amp;quot; Height=&amp;quot;3&amp;quot; Width=&amp;quot;5&amp;quot; RadiusX=&amp;quot;1&amp;quot; RadiusY=&amp;quot;1&amp;quot; Margin=&amp;quot;5,0,5,0&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot; Visibility=&amp;quot;Collapsed&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; /&amp;gt; 32:                                  &amp;lt;Rectangle Stroke=&amp;quot;#FFA3AEB9&amp;quot; StrokeThickness=&amp;quot;{TemplateBinding BorderThickness}&amp;quot; Fill=&amp;quot;#FFE6EFF7&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Grid.ColumnSpan=&amp;quot;3&amp;quot; Height=&amp;quot;3&amp;quot; RadiusX=&amp;quot;1&amp;quot; RadiusY=&amp;quot;1&amp;quot; Margin=&amp;quot;5,0,5,0&amp;quot;  Canvas.ZIndex=&amp;quot;0&amp;quot; /&amp;gt; 33:&amp;nbsp;  34:                                  &amp;lt;!-- Repeat Buttons &amp;#43; Thumb --&amp;gt; 35:                                  &amp;lt;RepeatButton x:Name=&amp;quot;HorizontalTrackLargeChangeDecreaseRepeatButton&amp;quot; IsTabStop=&amp;quot;False&amp;quot; Template=&amp;quot;{StaticResource RepeatButtonTemplate}&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot;/&amp;gt; 36:                                  &amp;lt;Rectangle x:Name=&amp;quot;LeftTrack&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Fill=&amp;quot;#00FFFFFF&amp;quot; Cursor=&amp;quot;Hand&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot;/&amp;gt; 37:                                  &amp;lt;Thumb Height=&amp;quot;18&amp;quot; x:Name=&amp;quot;HorizontalThumb&amp;quot; Width=&amp;quot;11&amp;quot; Grid.Column=&amp;quot;1&amp;quot; IsTabStop=&amp;quot;True&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot;/&amp;gt; 38:                                  &amp;lt;RepeatButton x:Name=&amp;quot;HorizontalTrackLargeChangeIncreaseRepeatButton&amp;quot; IsTabStop=&amp;quot;False&amp;quot; Template=&amp;quot;{StaticResource RepeatButtonTemplate}&amp;quot; Grid.Column=&amp;quot;2&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot;/&amp;gt; 39:                                  &amp;lt;Rectangle x:Name=&amp;quot;RightTrack&amp;quot; Grid.Column=&amp;quot;2&amp;quot; Fill=&amp;quot;#00FFFFFF&amp;quot; Cursor=&amp;quot;Hand&amp;quot; Canvas.ZIndex=&amp;quot;1&amp;quot;/&amp;gt; 40:                              &amp;lt;/Grid&amp;gt; 41:                          &amp;lt;/Grid&amp;gt; 42:                      &amp;lt;/ControlTemplate&amp;gt; 43:                  &amp;lt;/Setter.Value&amp;gt; 44:              &amp;lt;/Setter&amp;gt;</description>
	<link></link>
	<language>en</language>
	<pubDate>Wed, 22 May 2013 07:01:38 GMT</pubDate>
	<lastBuildDate>Wed, 22 May 2013 07:01:38 GMT</lastBuildDate>
	<generator>Rev9</generator>
	<item>
		<title>Re: New Custom Slider for Silverlight 2 media players</title>
		<description>
			<![CDATA[ <p>Hello Ben,<br><br>This is Rick over at uvntv.com<br><br>Can you make this code available for download<br><br>Thanks</p><p>posted by abner</p>]]>
		</description>
		<link>http://channel9.msdn.com/Blogs/benwagg/New-Custom-Slider-for-Silverlight-2-media-players#c633609795450000000</link>
		<pubDate>Thu, 30 Oct 2008 16:05:45 GMT</pubDate>
		<guid isPermaLink="true">http://channel9.msdn.com/Blogs/benwagg/New-Custom-Slider-for-Silverlight-2-media-players#c633609795450000000</guid>
		<dc:creator>abner</dc:creator>
	</item>
	<item>
		<title>Re: New Custom Slider for Silverlight 2 media players</title>
		<description>
			<![CDATA[ <p>Hello Ben,<br><br>This is Rick over at uvntv.com<br><br>Can you make this code available for download<br><br>Thanks</p><p>posted by abner</p>]]>
		</description>
		<link>http://channel9.msdn.com/Blogs/benwagg/New-Custom-Slider-for-Silverlight-2-media-players#c633609795450000000</link>
		<pubDate>Thu, 30 Oct 2008 16:05:45 GMT</pubDate>
		<guid isPermaLink="true">http://channel9.msdn.com/Blogs/benwagg/New-Custom-Slider-for-Silverlight-2-media-players#c633609795450000000</guid>
		<dc:creator>abner</dc:creator>
	</item>
</channel>
</rss>