views:

23

answers:

2

When I use the following line, implementing a templated control from a Silverlight class library;

<labelSliderControl:SliderControl x:Name="sldX" Label="X" Value="4" />

I see in the VS Disign view the Slider getting the value of 4. But when I run the app the Slider starts at 0. So when I change the attribute in XAML I can see the change, but I also want the value of 4 during runtime ofcourse. Is the depencyproperty overwriting the value in this case?

Here is the templated control from a Silverlight class library;

<Style TargetType="local:SliderControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:SliderControl">
                <Grid x:Name="LayoutRoot" Background="White">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <sdk:Label x:Name="lblLabel" Content="" HorizontalContentAlignment="Center" />
                    <Slider x:Name="sldValue" Grid.Row="1" Orientation="Vertical" />
                    <TextBox x:Name="txtValue" Grid.Row="2" MaxWidth="50" MinWidth="50" Text="{Binding ElementName=sldValue, Path=Value, StringFormat=\{0:N2\}}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

[TemplatePart(Name = "sldValue", Type = typeof(Slider)), TemplatePart(Name = "lblLabel", Type = typeof(Label))]
public class SliderControl : Control
{
    private Slider _sliderElement;

    private Slider SliderElement
    {
        get  { return _sliderElement; }
        set  {
            if (_sliderElement != null)
                _sliderElement.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(sldValue_ValueChanged);;

            _sliderElement = value;

            if (_sliderElement != null)
                _sliderElement.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sldValue_ValueChanged);
        }
    }

    public event EventHandler<ValueChangingEventArgs> ValueChanging;

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(double), typeof(SliderControl), new PropertyMetadata(0.0, ValuePropertyChanged));

    private static void ValuePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (obj is SliderControl)
        {
            SliderControl sliderUserControl = (SliderControl)obj;
            if (sliderUserControl.SliderElement != null)
            {
                sliderUserControl.SliderElement.Value = (double)args.NewValue;
            }
        }
    }

    public SliderControl()
    {
        this.DefaultStyleKey = typeof(SliderControl);
    }

    private void sldValue_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (ValueChanging != null)
        {
            ValueChanging(this, new ValueChangingEventArgs(e.OldValue, e.NewValue));
        }
    }

    public override void OnApplyTemplate()
    {
        SliderElement = GetTemplateChild("sldValue") as Slider;
        base.OnApplyTemplate();
    }
}
A: 

I don't see a "Value" Property as declared when registering the DependencyProperty.

public double Value
{
   get { return (double)base.GetValue(ValueProperty); }
   set { base.SetValue(ValueProperty, value); }
}

and then bind the property to the control in the constructor:

public SliderControl(){

   InitializeComponent();

   this.sldValue.SetBinding(Slider.ValueProperty, new Binding()
   {
      Source = this,
      Path = new PropertyPath("Value"),
      Mode = BindingMode.TwoWay
   });
}
gmcalab
Thanks for the quick reply.
Magiel
Thanks for the quick reply. The "Value" Property as declared when registering the DependencyProperty was mistakenly not posted. My apologies.I tried your interesting solution right away but I am trying to work with a Templated control. I assume because the OnApplyTemplateHas not been invoked yet, I don’t have an reference set to the Slider as Child control in my template control. Is it an idea to work with attached properties or I was also thinking about inheriting the whole templated control from silder and passing all properties through. I assume there must be a nicer solution.
Magiel
A: 

I got it to work ! I just put the solution of gmcalab in the OnApplyTemplate. Thanks to gmcalab.

    public override void OnApplyTemplate()
    {
        SliderElement = GetTemplateChild("sldValue") as Slider;
        if (SliderElement != null)
        {
            SliderElement.SetBinding(Slider.ValueProperty, new Binding()
            {
                Source = this,
                Path = new PropertyPath("Value"),
                Mode = BindingMode.TwoWay
            });
        }
        base.OnApplyTemplate();
    }
Magiel