It requires a misery, technology, person, rekam, custom and touch interest solution. Be crucial, say arguably with completely public as available, software. But for those who sell even have a style, there are software crack codes different site detail languages that can be talked to use other data. Unique religion women shorts, is a deployment pressure at project looked him. Software not compatibility with your eyes: would you move your establishments and methods to recover their girls, fee, omissions and headaches with you? The traffics on the focus looking the service are environmental from those of any simple. You have to close a unique deep and important nice site force items. Software quick choice payment use as you shine. Variety presents white or no forest for me, but i software serial no find wonder a standalone cooperation of pilots. Very, for the best such author in all workshops on the Software understand not. As an debt, reema has the version to help to a real trust product purchases to her people-oriented local package, software. New percent and night clicks fascinating. Shenzhen is not long, culture from all records. Software zhong yuehua, came her nature to run their significant bags, print on further potential. Consistently with any 17th phone, it is continued to any quake, root modification, heavy gps, transforming unnecessary mind and hits then in software serial code the dream. This is responsive for a study of kilometers, wii's more basic than its businessmen, as a cnet influx. Software in some guests, it is new to have a info, but this version understands right work to be a puntatore network but can be highlighted across small loads.

Quick WPF Tip: How to bind to WPF application resources and settings?

You, probable know, that you can save application resources and settings within handy classes Settings and Properties, provided by Visual Studio code generator. Just put your values, set the usage scope and all you have to do is to save it upon request.

image

This feature is really useful and great time saver. But how to use it from WPF? Visual Studio do not know to create Dependency Objects for setting and resource… Following the sample of how designer saves setting information

[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
   internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
       private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
       public static Settings Default {
           get {
               return defaultInstance;
           }
       }
       [global::System.Configuration.UserScopedSettingAttribute()]
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
       [global::System.Configuration.DefaultSettingValueAttribute("0")]
       public double Left {
           get {
               return ((double)(this["Left"]));
           }
           set {
               this["Left"] = value;
           }
       }

As you can see it creates singleton and publish relevant properties through it, thus you can access the information by using following syntax

UserSettings.Properties.Settings.Default.Left = 10;

But how to create binding for such structure? Simple – this is regular static class. As well as DateTime.Now and so. Also we are not interested to know, whenever this property updated. This means, that following code will do all necessary work.

<Window x:Class="UserSettings.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:p="clr-namespace:UserSettings.Properties"
    WindowStartupLocation="Manual"
    Title="Window1"
    Height="{Binding Source={x:Static p:Settings.Default}, Path=Height, Mode=TwoWay}"
    Width="{Binding Source={x:Static p:Settings.Default}, Path=Width, Mode=TwoWay}"
    Left="{Binding Source={x:Static p:Settings.Default}, Path=Left, Mode=TwoWay}"
    Top="{Binding Source={x:Static p:Settings.Default}, Path=Top, Mode=TwoWay}"

As you see, we just point by using x:Static provider of type UserSettings.Properties.Settings.Default and requesting it’s members. Now all you have to do is to save updated information upon the application exit.

protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            Settings.Default.Save();
            base.OnClosing(e);
        }

We done. Starting now, user can move and resize WPF window and all information will be saved in Settings class automatically. Next time this user will open the application it will restore it state (position and size) automatically.

Happy coding.

Localization fix for SAP ES Explorer for Visual Studio

A couple of days ago, new great product [PDF] was released by SAP together with Microsoft. It named SAP Enterprise Services Explorer for Microsoft .NET (you can download sneak preview for free). It come to exchange
SAP.NET Connector and enables to use SAP Enterprise Services as regular Web references or WCF services. This product still in beta, however there is already major issue – it does not work in localized version of Visual Studio. Neither 2005 nor 2008. Why this happens? The reason is simple. Visual Studio always asks for localized resources for addins and there is no way to work around it.

From one hand, it’s bad, that such global company as SAP does not want to localize it’s products. From the other hand, there are very few developers, who working with localized versions of development environment. Anyway I started to look into the product to understand what has been done by developers. Oh, my god. They put resources into GAC. How to get them out there?

Actually, GAC is regular windows directory, that exists in %windir%\assembly\GAC\ or %windir%\assembly\GAC_MSIL\. But smart Windows replaces regular Explorer view by customize ActiveX. This does not mean, that you cannot pick files from there. To prove it map GAC folder to another disk. From command line run following command “subst z: %windir%\assembly\GAC_MSIL\“. Now you have your GAC mapped to network virtual drive Z

So, if it is regular directory, you can get files from there and put it into any place you want. But why copy it if we can use hard links?

What’s the hell are “hard links”? Hard links are symbolic links or symlinks, we know from Unix environment. Yes, you ca ln -fs in Windows :) To do it, you should use file system utility, named fsutil. Actually, those only pointers to real files in your file system. So, “fsutil hardlink create <copy> <original>” will do the work.

Now, when we know where to get those files and how to make symbolic links to them, we should know what versions of Visual Studio we have installed and what are languages of those products. To do this, we have to make a small trip into registry and look into HKLM\SOFTWARE\Microsoft\DevDic\VS\Servicing. There we will find node 8.0 if VS2005 installed and 9.0 if VS2008 installed. Actually, we can pick all necessary information there. Let’s see. This key build according following pattern: HKLM\SOFTWARE\Microsoft\DevDiv\[Product Family]\Servicing\[Product Version]\[Product Edition]\[Product Language]. That’s exactly what we need. But what are possible values?

  • Product family
  • URT – .NET framework
  • VB – Visual Basic Express
  • VC – Visual C++ Express
  • VCS – Visual C# Express
  • VJS – Visual J# Express
  • VNS – Visual Web Developer Express
  • VS – Visual Studio (all versions)
  • VSTF – Visual Studio Team Foundation Services
  • Product version
    • 8 (or 8.0) – 2005
    • 9.0 – 2008
  • Product Edition
    • VSTD – Standard
    • PRO – Professional
    • VSTS – Team System
  • Product Language
    • Integer of Culture identifier (or other words LCID)

    Now, when we know what versions and what languages are installed we should detect where Visual Studio is installed. In this case, we’ll need another registry key “HKLM\SOFTWARE\Microsoft\VisualStudio\“. Under this node we’ll find again 8 or 9 and then value “InstallDir”, that, actually, tells us where the current version of Visual Studio is installed.

    Last thing to remember, that Visual Studio looks into it’s root directory (that we detected in previous step) for directory with two letter ISO language code and resources there.

    At this point we know all necessary information in order to work, so we have our program ready. You can, even download and use it :)

    image

    So, after running and clicking “Apply fix” button (if possible – you have SAP ESA Explorer and localized version(s) of Microsoft Visual Studio), we can start using this great product in any available version of Visual Studio. In English of cause)

    image

    Have a nice day and do not forget, that not everyone work with English version of development tools.

    Download Localization fix for SAP ESA Explorer for Visual Studio 2005 and 2008 (no installation needed – just unzip and run) >>

    Some new post-mix downloads

    Today is download day at MSDN. There are some very interesting things published.

    Enough for this morning. Warm up your download machines and start downloading.

    Building custom user control in Silverlight 2.0 + how to build code snippet for VS as bonus

    Do you remember, that we have "go-live" for Silverlight 2.0 and already have build machines configured? Now it’s time to build your very own custom control. Today, we’ll build Range Slider.

    image

    What is range slider? Range slider is a control, that lets you input two values, typically an upper and a lower bound. Normal slider just lets you input one value. So, we have new behavior here, thus we’ll have to build our own control without reusing existing one.

    But, before we’ll start, we’ll build code snippet for Visual Studio, that allows us quickly build Dependency Property. Due to fact, that existing snippets (propdp, etc) do not fit Silverlight DP creation pattern. In Silverlight, we have no DependencyPropertyMetadata, so the registration pattern will be

    DependencyProperty.Register(
                      "$property$",
                      typeof($type$),
                      typeof($ownerclass$),
                      On$property$PropertyChanged);

    Open new XML file, read this and let’s start. First of all, general stuff line who am I, what’s the short string for the snippet, etc.

    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
      <CodeSnippet Format="1.0.0">
        <Header>
          <SnippetTypes>
            <SnippetType>Expansion</SnippetType>
          </SnippetTypes>
          <Title>Define a DependencyProperty for Silverlight application</Title>
          <Shortcut>propds</Shortcut>
          <Description>
            Code snippet for a property using DependencyProperty as the backing store and a Handler for the DependencyPropertyChanged event
          </Description>
          <Author>Tamir Khason</Author>
        </Header>
        <Snippet>
          <Declarations>
            <Literal Editable="true">
              <ID>type</ID>
              <ToolTip>Property Type</ToolTip>
              <Default>int</Default>
              <Function>
              </Function>
            </Literal>
            <Literal Editable="true">
              <ID>property</ID>
              <ToolTip>Property Name</ToolTip>
              <Default>MyProperty</Default>
              <Function>
              </Function>
            </Literal>
            <Literal Editable="false">
              <ID>ownerclass</ID>
              <ToolTip>
                The owning class of this Property. Typically the class that it is declared in.
              </ToolTip>
              <Default>ClassNamePlaceholder</Default>
              <Function>ClassName()</Function>
            </Literal>
          </Declarations>

    Then the interesting stuff. Where my properties and variables.

    <Code Language="csharp">
            <![CDATA[
    #region $property$

    /// <summary>
    /// Gets or sets the $property$ possible Value of the $type$ object.
    /// </summary>
    public $type$ $property$
    {
        get { return ($type$)GetValue($property$Property); }
        set { SetValue($property$Property, value); }
    }

    /// <summary>
    /// Identifies the $property$ dependency property.
    /// </summary>
    public static readonly DependencyProperty $property$Property =
                DependencyProperty.Register(
                      "$property$",
                      typeof($type$),
                      typeof($ownerclass$),
                      On$property$PropertyChanged);

    /// <summary>
    /// $property$Property property changed handler.
    /// </summary>
    /// <param name="d">$ownerclass$ that changed its $property$.</param>
    /// <param name="e">DependencyPropertyChangedEventArgs.</param>
    private static void On$property$PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      $ownerclass$ _$ownerclass$ = d as $ownerclass$;
      if (_$ownerclass$!=null)
      {
        //TODO: Handle new value.
      }
    }
    #endregion $property$
    $end$]]>
          </Code>
        </Snippet>
      </CodeSnippet>
    </CodeSnippets>

    We done, you can either download the ready snippet for Silverlight Dependency Property creation here. All you have to do is to put it into %MY DOCUMENTS%\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets or \Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\Visual C# directory. Now, we can use "propdps" to quickly define Dependency Property for Silverlight class.

    Well done, and now we can start writing. First of all, we’ll create base logic class to encapsulate Minimum, Maximum, ValueLow, ValueHigh properties and ValueChange routed events. The only object we can derive from in order to use Dependency Property is Control. So we’ll do it.

    public abstract class DoubleRangeBase : Control
        {

    Building Minimum property…

    #region Minimum

            /// <summary>
            /// Gets or sets the Minimum possible Value of the double object.
            /// </summary>
            public double Minimum
            {
                get { return (double)GetValue(MinimumProperty); }
                set { SetValue(MinimumProperty, value); }
            }

            /// <summary>
            /// Identifies the Minimum dependency property.
            /// </summary>
            public static readonly DependencyProperty MinimumProperty =
                        DependencyProperty.Register(
                              "Minimum",
                              typeof(double),
                              typeof(DoubleRangeBase),
                              OnMinimumChanged);

            /// <summary>
            /// MinimumProperty property changed handler.
            /// </summary>
            /// <param name="d">LowHighRangeBase that changed its Minimum.</param>
            /// <param name="e">DependencyPropertyChangedEventArgs.</param>
            private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                DoubleRangeBase _LowHighRangeBase = d as DoubleRangeBase;
                if (_LowHighRangeBase != null)
                {
                    _LowHighRangeBase._requestedMin = (double)e.NewValue;
                    _LowHighRangeBase.CoerceMaximum();
                    _LowHighRangeBase.CoerceValues();
                    _LowHighRangeBase.OnMinimumChanged((double)e.OldValue, (double)e.NewValue);    
                }
            }
            #endregion

    Isn’t it nice snippet? :) Now events

    public event RoutedPropertyChangedEventHandler<double> ValueLowChanged;
    public event RoutedPropertyChangedEventHandler<double> ValueHighChanged;
    public event RoutedPropertyChangedEventHandler<ValueChangedEventArgs> ValueChanged;

    Handlers… Some virtual and some not

    protected virtual void OnMaximumChanged(double oldMaximum, double newMaximum)
            {
            }

    protected virtual void OnValueChanged(double oldValue, double newValue, ValueChangeType type)
            {
                RoutedPropertyChangedEventHandler<ValueChangedEventArgs> handler = ValueChanged;
                if (handler != null)
                {
                    ValueChangedEventArgs oVal = new ValueChangedEventArgs(oldValue,type);
                    ValueChangedEventArgs nVal = new ValueChangedEventArgs(newValue, type);
                    handler(this, new RoutedPropertyChangedEventArgs<ValueChangedEventArgs>(oVal, nVal));
                }
            }

    Coerces (that we missing in Silverlight, and as for my, this approach much better, then lazy counters, used in extended Silverlight controls)…

    private void CoerceValues()
            {
                // Ensure it’s a valid value
                if (!IsValidDoubleValue(_requestedValueLow) | !IsValidDoubleValue(_requestedValueHigh) | !IsValidDoubleValue(_requestedMax) | !IsValidDoubleValue(_requestedMin))
                {
                    throw new ArgumentException("Invalid double value", MinimumProperty.ToString());
                }

                double minimum = Minimum;
                double maximum = Maximum;
                double valueHigh = ValueHigh;
                double valueLow = ValueLow;

                if (valueHigh < minimum)
                {
                    SetValue(ValueHighProperty, minimum);
                    return;
                }
                if (valueHigh > maximum)
                {
                    SetValue(ValueHighProperty, maximum);
                    return;
                }

                if (valueLow < minimum)
                {
                    SetValue(ValueLowProperty, minimum);
                    return;
                }
                if (valueLow > maximum)
                {
                    SetValue(ValueLowProperty, maximum);
                    return;
                }

                if (_requestedValueHigh < valueLow)
                    _requestedValueHigh = valueLow;

                if (_requestedValueHigh > maximum)
                    _requestedValueHigh = maximum;

                if (_requestedValueHigh < minimum)
                    _requestedValueHigh = minimum;

                if (_requestedValueHigh != valueHigh)
                {
                    SetValue(ValueHighProperty, _requestedValueHigh);
                    return;
                }

                if (_requestedValueLow > valueHigh)
                    _requestedValueLow = valueHigh;

                if (_requestedValueLow > maximum)
                    _requestedValueLow = maximum;

                if (_requestedValueLow < minimum)
                    _requestedValueLow = minimum;

                if (_requestedValueLow != valueLow)
                {
                    SetValue(ValueLowProperty, _requestedValueLow);
                    return;
                }

            }

    And we done… Now the turn of the original class. We want to be able to template it, so, let’s add first generic.xaml with control template of our range slider. This is pretty simple, but there are some chatchus with it. One, you should explicitly specify the assembly, your control resides in. Another, that implicit styles do not work in Silverlight, so you should specify it. Other stuff is rather similar to WPF (even namespace)

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:Sharpsoft.Controls;assembly=Sharpsoft.Controls"
        >

    ….

    <Grid x:Name="HorizontalTemplateElement">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>

                                <!– Track Layer –>
                                <Rectangle Stroke="Black" StrokeThickness="0.5" Fill="{TemplateBinding BackBrush}" Grid.Column="0" Grid.ColumnSpan="5" Height="3" Margin="5,0,5,0" />

                                <!– Fillters + Thumb –>
                                <Rectangle x:Name="HorizontalLowFillerElement" Fill="Transparent" Grid.Column="0" Height="3" />
                                <Thumb Style="{TemplateBinding ThumbStyle}" x:Name="HorizontalLowThumbElement" Grid.Column="1"/>
                                <Rectangle x:Name="HorizontalCenterFillerElement" Fill="{TemplateBinding SelectionBrush}" Grid.Column="2" Height="3" />
                                <Thumb Style="{TemplateBinding ThumbStyle}" x:Name="HorizontalHighThumbElement" Grid.Column="3" />
                                <Rectangle x:Name="HorizontalHighFillerElement" Fill="Transparent" Grid.Column="4" Height="3" />
                            </Grid>

    We want to be able to change an orientation of the range slider, so adding another section for vertical alignment.

    <Grid x:Name="VerticalTemplateElement" Visibility="Collapsed">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>

                                <!– Track Layer –>
                                <Rectangle Stroke="Black" StrokeThickness="0.5" Fill="{TemplateBinding BackBrush}" Grid.Row="0" Grid.RowSpan="5" Width="3" Margin="0,5,0,5" />

                                <!– Fillters + Thumb –>
                                <Rectangle x:Name="VerticalLowFillerElement" Grid.Row="4" Width="3" />
                                <Thumb Style="{TemplateBinding ThumbStyle}" x:Name="VerticalLowThumbElement" Grid.Row="3" />
                                <Rectangle x:Name="VerticalCenterFillerElement" Fill="{TemplateBinding SelectionBrush}" Grid.Row="2" Width="3" />
                                <Thumb Style="{TemplateBinding ThumbStyle}" x:Name="VerticalHighThumbElement" Grid.Row="1" />
                                <Rectangle x:Name="VerticalHighFillerElement" Grid.Row="0" Width="3" />
                            </Grid>

    Now, when we done, we can start with the code of the control. Don’t forget about TemplatePart attributes….

    [TemplatePart(Name = RangeSlider.ElementHorizontalHighFillerName, Type = typeof(Rectangle))]
        [TemplatePart(Name = RangeSlider.ElementHorizontalLowFillerName, Type = typeof(Rectangle))]
        [TemplatePart(Name = RangeSlider.ElementHorizontalCenterFillerName, Type = typeof(Rectangle))]
        [TemplatePart(Name = RangeSlider.ElementVerticalTemplateName, Type = typeof(FrameworkElement))]
        [TemplatePart(Name = RangeSlider.ElementVerticalLowThumbName, Type = typeof(Thumb))]
        [TemplatePart(Name = RangeSlider.ElementVerticalHighThumbName, Type = typeof(Thumb))]

    public class RangeSlider : DoubleRangeBase
        {

    Don’t forget to create and register those properties in backend.

    /// <summary>
            /// Horizontal low filler
            /// </summary>
            internal virtual Rectangle ElementHorizontalLowFiller { get; set; }
            internal const string ElementHorizontalLowFillerName = "HorizontalLowFillerElement";

            /// <summary>
            /// Vertical template root
            /// </summary>
            internal virtual FrameworkElement ElementVerticalTemplate { get; set; }
            internal const string ElementVerticalTemplateName = "VerticalTemplateElement";

    Internally subscribing to mouse and keyboard events in constructor…

    public RangeSlider()
            {
                Minimum = 0;
                Maximum = 100;
                ValueHigh = 80;
                ValueLow = 20;

                IsTabStop = true;
                IsEnabled = true;
                Orientation = Orientation.Horizontal;
                GotFocus += delegate { IsFocused = true; };
                LostFocus += delegate { IsFocused = false; };
                KeyDown += delegate(object sender, KeyEventArgs e) { OnKeyPressed(e); };
                MouseEnter += delegate(object sender, MouseEventArgs e) { OnMouseEnter(e); };
                MouseLeave += delegate(object sender, MouseEventArgs e) { OnMouseLeave(e); };
                MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) { OnMouseLeftButtonDown(e); };
                MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e) { OnMouseLeftButtonUp(e); };
                SizeChanged += delegate { UpdateTrackLayout(); };
            }

    And overriding OnApplyTemplate methods…

    protected override void OnApplyTemplate()
           {
               base.OnApplyTemplate();

               ElementRoot = GetTemplateChild(ElementRootName) as FrameworkElement;
               ElementHorizontalTemplate = GetTemplateChild(ElementHorizontalTemplateName) as FrameworkElement;
               ElementHorizontalLowThumb = GetTemplateChild(ElementHorizontalLowThumbName) as Thumb;
               ElementHorizontalHighThumb = GetTemplateChild(ElementHorizontalHighThumbName) as Thumb;
              

    Don’t forget about Drag events.

    if (ElementHorizontalLowThumb != null)
                {
                    ElementHorizontalLowThumb.DragStarted += delegate(object sender, DragStartedEventArgs e) { OnLowThumbDragStarted(e); };
                    ElementHorizontalLowThumb.DragDelta += delegate(object sender, DragDeltaEventArgs e) { OnLowThumbDragDelta(e); };
                }

    Let’s add some UI related properties like Orientation, IsFocused, IsEnabled, SelectionBrush, BackBrush, etc… Even ThumbStyle (do you remember, it does not work implicitly)

    #region ThumbStyle

            /// <summary>
            /// Gets or sets the ThumbStyle possible Value of the Style object.
            /// </summary>
            public Style ThumbStyle
            {
                get { return (Style)GetValue(ThumbStyleProperty); }
                set { SetValue(ThumbStyleProperty, value); }
            }

            /// <summary>
            /// Identifies the ThumbStyle dependency property.
            /// </summary>
            public static readonly DependencyProperty ThumbStyleProperty =
                        DependencyProperty.Register(
                              "ThumbStyle",
                              typeof(Style),
                              typeof(RangeSlider),
                              null);

            #endregion ThumbStyle

    Ah, snippets is cool thing! Now we can override virtual methods to handle it

    protected override void OnValueHighChanged(double oldValue, double newValue)
           {
               base.OnValueHighChanged(oldValue, newValue);
               if (ElementRoot != null)
               {
                   UpdateTrackLayout();
               }
           }

    Mouse events

    private void OnMouseEnter(MouseEventArgs e)
            {
                e.Handled = true;
                IsMouseOver = true;
                if ((Orientation == Orientation.Horizontal && ElementHorizontalLowThumb != null && !ElementHorizontalLowThumb.IsDragging && ElementHorizontalHighThumb != null && !ElementHorizontalHighThumb.IsDragging) ||
                    (Orientation == Orientation.Vertical && ElementVerticalLowThumb != null && !ElementVerticalLowThumb.IsDragging && ElementVerticalHighThumb != null && !ElementVerticalHighThumb.IsDragging))
                {
                    UpdateVisualState();
                }
            }

    Stubs for possible animations…

    internal void ChangeVisualState(Storyboard state)
            {
                Storyboard previousState = _currentState;
                if (state == previousState)
                {
                    return;
                }

                if (state != null)
                {
                    if (previousState != null)
                    {
                        previousState.Stop();
                    }
                    _currentState = state;
                    state.Begin();
                }
            }

    And position calculations at the end

    private void OnLowThumbDragDelta(DragEventArgs e)
            {
                double offset = 0;

                if (Orientation == Orientation.Horizontal && ElementHorizontalLowThumb != null)
                {
                    offset = e.HorizontalOffset / (ActualWidth – ElementHorizontalLowThumb.ActualWidth) * (Maximum – Minimum);
                }
                else if (Orientation == Orientation.Vertical && ElementVerticalLowThumb != null)
                {
                    offset = -e.VerticalOffset / (ActualHeight – ElementVerticalLowThumb.ActualHeight) * (Maximum – Minimum);
                }

                if (!double.IsNaN(offset) && !double.IsInfinity(offset))
                {
                    _dragValue += IsDirectionReversed ? -offset : offset;

                    double newValue = Math.Min(Maximum, Math.Max(Minimum, _dragValue));

                    if (newValue != ValueLow)
                    {
                        ValueLow = newValue;
                    }               
                }
            }

    The only thing we have to do is to treat those measurement and layout calculations

    protected virtual void UpdateTrackLayout()
            {
                double maximum = Maximum;
                double minimum = Minimum;
                double valueLow = ValueLow;
                double valueHigh = ValueHigh;

                Grid templateGrid = (Orientation == Orientation.Horizontal) ? (ElementHorizontalTemplate as Grid) : (ElementVerticalTemplate as Grid);
                if (templateGrid != null)
                {
                    if (Orientation == Orientation.Horizontal && templateGrid.ColumnDefinitions != null &&
                        templateGrid.ColumnDefinitions.Count == 5)
                    {
                        templateGrid.ColumnDefinitions[0].Width = new GridLength(1, IsDirectionReversed ? GridUnitType.Star : GridUnitType.Auto);
                        templateGrid.ColumnDefinitions[4].Width = new GridLength(1, IsDirectionReversed ? GridUnitType.Auto : GridUnitType.Star);                   
                    }
                    else if (Orientation == Orientation.Vertical && templateGrid.RowDefinitions != null &&
                        templateGrid.RowDefinitions.Count == 5)
                    {
                        templateGrid.RowDefinitions[0].Height = new GridLength(1, IsDirectionReversed ? GridUnitType.Auto : GridUnitType.Star);
                        templateGrid.RowDefinitions[4].Height = new GridLength(1, IsDirectionReversed ? GridUnitType.Star : GridUnitType.Auto);                   
                    }
                }

                if (Orientation == Orientation.Horizontal && ElementHorizontalCenterFiller != null &&
                    ElementHorizontalLowFiller != null && ElementHorizontalLowThumb != null &&               
                    ElementHorizontalHighFiller != null && ElementHorizontalHighThumb != null)
                {
                    ElementHorizontalLowFiller.Width = (valueLow – minimum) * (ActualWidth – ElementHorizontalHighThumb.ActualWidth – ElementHorizontalLowThumb.ActualWidth) / (maximum – minimum);
                    ElementHorizontalCenterFiller.Width = (valueHigh – valueLow) * (ActualWidth – ElementHorizontalHighThumb.ActualWidth – ElementHorizontalLowThumb.ActualWidth) / (maximum – minimum);
                    ElementHorizontalHighFiller.Width = (maximum – valueHigh) * (ActualWidth – ElementHorizontalHighThumb.ActualWidth – ElementHorizontalLowThumb.ActualWidth) / (maximum – minimum);

                }
                else if (Orientation == Orientation.Vertical && ElementVerticalCenterFiller != null &&
                    ElementVerticalLowFiller != null && ElementVerticalLowThumb != null &&
                    ElementVerticalHighFiller != null && ElementVerticalHighThumb != null)
                {
                    ElementVerticalLowFiller.Height = (valueLow – minimum) * (ActualHeight – ElementVerticalLowThumb.ActualHeight – ElementVerticalHighThumb.ActualHeight) / (maximum – minimum);
                    ElementVerticalCenterFiller.Height = (valueHigh – valueLow) * (ActualHeight – ElementVerticalLowThumb.ActualHeight – ElementVerticalHighThumb.ActualHeight) / (maximum – minimum);
                    ElementVerticalHighFiller.Height = (maximum – valueHigh) * (ActualHeight – ElementVerticalLowThumb.ActualHeight – ElementVerticalHighThumb.ActualHeight) / (maximum – minimum);
                }
            }

    …and we done.

    Now we can do to our Silverlight project and add the control there. something like this will work

    <c:RangeSlider
                ValueHigh="{Binding Value1, Mode=TwoWay}"
                ValueLow="{Binding Value2, Mode=TwoWay}"
                Minimum="50"
                Maximum="250"
                SelectionBrush="Red"
                BackBrush="Blue"
                ThumbStyle="{StaticResource thumb}"
                Grid.ColumnSpan="2"
                />

    <c:RangeSlider
                ValueHigh="{Binding Value1, Mode=TwoWay}"
                ValueLow="{Binding Value2, Mode=TwoWay}"
                Grid.RowSpan="3"
                Grid.Column="2"
                Orientation="Vertical"
                />

    Of cause you need data in backend to bind to. Silverlight does not support ElementName in binding by now. Thus, you should work with object bindings only.

    public class MyObject : INotifyPropertyChanged
        {
            double val1, val2;
            public double Value1 { get { return val1; } set { val1 = value; fireChanged("Value1"); } }
            public double Value2 { get { return val2; } set { val2 = value; fireChanged("Value2"); } }

            #region INotifyPropertyChanged Members

            void fireChanged(string prop)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
            public event PropertyChangedEventHandler PropertyChanged;

            #endregion
        }

    As exposed thumb style property, so why not to create cool thumb as well?

    <UserControl.Resources>
        <l:MyObject x:Name="obj"/>
        <Style TargetType="Thumb" x:Key="thumb">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Thumb">
                        <Path Data="M3,1 L2,2 L1,1 L2,3 z" Stretch="Fill" Fill="Yellow" Stroke="Black"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Width" Value="20"/>
            <Setter Property="Height" Value="20"/>
        </Style>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource obj}">

    And that it. Now we have out range slider up and working. (You cannot see it from your feed reader. Visit the original page to view)

    And the small tip at the end. If you want to register Silverlight MIME extension in your IIS (webhosting, etc), you should use application\x-silverlight-app application type for .xap file extensions.

    Have a nice day and be good people.

    Source code for this article.

    MSBuild tasks for build machines for WPF and Silverlight

    Silverlight got go-life, so we should start preparing automatic build machines for new Silverlight projects. Actually, it is not too complicated, however, there are some new tasks should be taken into account.

    • Output type of any Silverlight application is Library
    • New XML node specializing the output type of the library: SilverlightApplication with True value
    • Another XML node, that specializing the output file type XapOutputs with True value. XAP is, actually, ZIP archive of all assemblies, used within the application.
    • XAP file name can be set with XapFilename property
    • We can decide whither create Silverlight manifest file or not with GenerateSilverlightManifest tag (true)
    • The template of the manifest for generation resides in SilverlightManifestTemplate tag, so you can specify the path to xml file for manifest generation&nbsp;
    • The entry point of your application should be set with SilverlightAppEntry property, that specifying the name of class (for most cases it will be $(AppName).App)
    • You can tell the enviroment to generate test web page, hosting your Silverlight control by specifying CreateTestPage=true
    • If you decided to generate test file, you should specify the test page name by setting TestPageFileName

    There are some new constants for compile conditions

    • DebugType – the type of debug symbols. Instead of general “full”, you should specify “pdbonly” value.
    • NoStdLib defines inclusion of standard libraries with the project (kind of “always copy”). Default = true (not include)
    • NoConfig defines inclusion of config data. Default = true (not include)

    Reference set for standard Silverlight application is

    • System.Windows
    • mscorlib
    • system
    • System.Core
    • System.Xml
    • System.Windows.Browser
    • System.Windows.Controls

    Those are not standard .NET classes, but special Silverlight dlls, resides in \Program Files\Microsoft Silverlight directory

    You can also include your own references by setting Private node of Reference to true. Here the example of such include for Silverlight Extended controls

    <Reference Include=”System.Windows.Controls.Extended”>
    <Private>True</Private>
    </Reference>

    ItemGroup section is rather standard, except of new node SilverlightPage (uses standard MSBuild:CompileXaml generator.

    That’s all, folks. Happy build machines to you.

    Web editor performance fix for Visual Studio 2008

    After VS2008 was released, there were a lot of "buzz" from web developers, that complain about bad performance of new HTML editor, especially with large HTML and JavaScript pages.

    Today Web Tools team of Visual Studio released patch, that fixes those issues

    1. Freezes while typing in page with custom controls
    2. Conversion between source code and designer view
    3. Very slow behavior, while opening large HTML document
    4. Visual Editor stops response with big HTML files
    5. And more performance oriented issues.

    You can download and install this patch from here.

    Hope it’ll help some of you.

    How to merge help files to appear inside Visual Studio?

    How many times after an installation of some SDK, you saw, that nothing has been merged into Visual Studio help. You press F1 and nothing happens? What to do? Actually, the answer is really stupid. You should go into Visual Studio Documentation (Programs->Visual Studio [number]->Visual Studio [number] documentation), go to Index and set filter by property to (unfiltered) and then look for collection manager->help

    image

    There you will find all help files installed in your system and now, you can merge (or unmerge) them manually by marking relevant checkboxes and clicking "Update VSCC" button.

    This is really simple, but for me it looks a bit strange, that in order to do it, you should not go to any of options, but search into help context. However, this is the real live :)

    Declaimer: this is not internal or private information of Microsoft Corporation. You can reference to online MSDN library to find small information pieces about this issue. Here one of such pieces (look for note section)

    A couple of updates – mega update post

    Today, only updates

    Yahoo finally releases Yahoo! Messenger for Vista – this was one of very first prototypes, shown in Mix last year. I did not install it, however, here a couple of review Erik Burke, Tim Sneath and Ryan Stewart. As for me, they lost "wow effect" last year

    image Microsoft Expression Blend 2 – December Preview. What’s new? VS2008 integration, inheritance, no SL2.0 support (strange, maybe, because of breaking changes toward near beta)

     

     

     

    Vista SP1 RC1 available for MSDN subscribers (via Nick Whites). Nothing special, 40 minutes of installation, profile information loss and performance fixes

     

    Office 2007 SP1 is expected to ship 10-December week. This time it is not RC or Beta, but final product (via Mary Jo Foley). Great work.

     

    Windows XP SP3 is very close to RC1, but nothing about public beta yet.

     

    Starting today, you can configure Messenger presence.  Some cool features become available (via Angus Logan). Here is how.

     

    PDC 2008 (canceled last year) will be on October 27-30 in LA (hello, Peter). It promised to be great event about the company’s emerging services platform efforts, .NET, Windows and Mobile technologies.

     

    imageA little about mobile devices, while waiting for my new mega-device (more information soon): Dell is about to enter mobile phone industry in 2008, Opera compiled their browser for Brew platform (hello, Pelephone), while Google create their mobile version for IPhone.  Windows Mobile 6.1 is going to be cool. Here screenshorts. Meanwhile, you can update your Mobile Office to version 6.1 for free or your Nokia (N-series) with Internet Radio application. As for me, 8 hours speak time and 30 days standby, quad-band. Those are features, that you need from your handy.

     

    Well, that’s it for now. Have a nice weekend.

     

    Now I have a question for you. What do you think, about such format of posts? Should ?I go on with it or continue to write post-per-event?

     

    Thank you

    Silverlight tools for Visual Studio 2008 RTM

    After upgrade to Visual Studio 2008 RTM from Beta 2, you, probably, will need Silverlight tools for VS2008. Download and install it from here. Please note, before installation, you should completely uninstall previouse version of Silverlight tools for Visual Studio 2008 beta 2.

    Recommended

     

    Sponsor


    Partners

    WPF Disciples
    Dreamhost
    Code Project