Denis
Denis

Reputation: 344

Changing binding mode on Slider caused to change value

I have sliders with twoway binding enabled at startup. But when I move them, moving is not smooth enought. So, I decide to change binding mode from twoway to onewaytosource after Thumbs.DragStarted event is called, but this lead to immediate changing value from 1 to 0.

My question is: How to prevent slider from changing its value during new binding?

My code behind is below.

    private void SliderCameraZ_OnDragStarted(object sender, DragStartedEventArgs e)
    {
        try
        {
            BindingExpression bindingExpression = ((Slider) sender).GetBindingExpression(Slider.ValueProperty);
            BindingOperations.ClearBinding((Slider) sender, Slider.ValueProperty);
            Binding binding = new Binding();
            binding.Path = bindingExpression.ParentBinding.Path;
            binding.Mode = BindingMode.OneWayToSource;
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            ((Slider)sender).SetBinding(Slider.ValueProperty, binding);

        }
        catch (Exception exception)
        {
            MessageBox.Show(exception.Message + exception.StackTrace + exception.TargetSite);
        }
    }

Upvotes: 2

Views: 1379

Answers (2)

Denis
Denis

Reputation: 344

All was simple. I just need to store value of slider and restore it after new binding is set.

Upvotes: 0

LPL
LPL

Reputation: 17063

In most cases it should be enough using the Delay Property introduced in .Net 4.5 to reduce the update calls taking to much time. For a sample see Adding a delay to your binding updates to reduce noise:

<StackPanel>
    <Slider x:Name="ValueSlider"
            Minimum="0" Maximum="100"
            Margin="20" Height="25"
            Value="{Binding ElementName=ValueText, Delay=500, Path=Text, Mode=TwoWay}" />
    <TextBox x:Name="ValueText" Text="50"
             Width="100" Height="50" FontSize="20"
             HorizontalAlignment="Center" /> 
</StackPanel>

If you really need an immediate update you can still call BindingExpression.UpdateSource Method respective BindingExpression.UpdateTarget Method:

BindingExpression bindingExpression = ValueSlider.GetBindingExpression(Slider.ValueProperty);
bindingExpression.UpdateSource();

But your question is about preventing the value change after changing the binding mode. I've noticed that this only appears with BindingMode.OneWayToSource. Maybe you can avoid this by changing the sample above to

<StackPanel>
    <Slider x:Name="ValueSlider"
            Minimum="0" Maximum="100"
            Margin="20" Height="25"
            Value="50" />
    <TextBox x:Name="ValueText"
             Text="{Binding ElementName=ValueSlider, Path=Value, Mode=TwoWay}"
             Width="100" Height="50" FontSize="20"
             HorizontalAlignment="Center" /> 
</StackPanel>

Now the TextBox is bound to Slider and not the other way round. BindingMode.OneWayToSource would be BindingMode.OneWay and a binding change shouldn't cause a value change.

BindingExpression bindingExpression = ValueText.GetBindingExpression(TextBox.TextProperty);
Binding binding = new Binding();
binding.Source = bindingExpression.DataItem;
binding.Path = bindingExpression.ParentBinding.Path;
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
ValueText.SetBinding(TextBox.TextProperty, binding);

Upvotes: 1

Related Questions