Reputation: 119
So I have a ScrollBar whose Maximum property binds to a dependency object, and I want the LargeChange and SmallChange properties to always be constant fractions of this length. I currently implement this in the code-behind but am trying to switch to an all-XAML approach.
So instead of this:
curSpeedScrollbar.SetBinding(Slider.MaximumProperty, speedBinding);
curSpeedScrollbar.LargeChange = curSpeedScrollbar.Maximum / 1000;
curSpeedScrollbar.SmallChange = curSpeedScrollbar.Maximum / 10000;
curSpeedScrollbar.ViewportSize = curSpeedScrollbar.Maximum / 16;
I'm shooting for something like this (but with the correct syntax):
<ScrollBar BorderThickness="1" Height="25" HorizontalAlignment="Stretch" LargeChange = "Maximum / 1000" Margin="208,62,130,106" Maximum="{Binding MaxValue}" Name="curSpeedScrollbar" Orientation="Horizontal" SmallChange = "Maximum / 10000" VerticalAlignment="Stretch" ViewportSize="Maximum / 16" Width="431" Grid.Column="2" Grid.Row="1" />
Can anyone show me the proper syntax to do this? Or if there is a better way to achieve what I want (no/minimal code-behind, all/mostly in XAML)? Thanks!
Upvotes: 1
Views: 1482
Reputation: 20770
There are two parts to your question, so I will respond to each of them individually:
How to bind to a property from within a property
This is possible, and in fact, it is constantly done - bindings are (almost) always added from a property to refer to another property. Normally, you just do not refer to another property of the same object, but this can be done with RelativeSourceMode.Self
:
LargeChange="{Binding Maximum, RelativeSource={RelativeSource Self}}"
How to bind to a multiplied value of a property
For this, you will have to create a value converter. A very static version of such a converter could look like this:
public class DividingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double)value) / 1000;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
You may have to check value
for DependencyProperty.UnsetValue
, as sometimes, dependency properties are unset at some point.
For a more dynamic version, you can use the ConverterParameter
property from bindings to supply the value to divide by.
This converter can then be added as a static resource in your XAML:
<somewhere:DividingConverter x:Key="divConv"/>
(where somewhere
is a namespace prefix for your converter namespace)
It can then be used in bindings such as the above one:
LargeChange="{Binding Maximum, RelativeSource={RelativeSource Self}, Converter={StaticResource divConv}}"
Upvotes: 2
Reputation: 4298
To just bind some property to the value of another property of the same control, you can use RelativeSource.Self
:
<ScrollBar Maximum="{Binding MaxValue}" SmallChange="{Binding RelativeSource={RelativeSource Self}, Path=Maximum}" ... />
This would set SmallChange
to the same value as Maximum
.
However, this is as far as you get, since calculations are not possible directly within XAML. For this you'd need a converter that, for example, takes the Maximum
property's value as input and returns the calculation's result.
Upvotes: 1
Reputation: 41
You can use a converter to achieve this behavior.
A math converter for these operations can be found here: http://www.codeproject.com/Articles/239251/MathConverter-How-to-Do-Math-in-XAML
Upvotes: 2