reservoirman
reservoirman

Reputation: 119

Can you reference properties within other properties in XAML?

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

Answers (3)

O. R. Mapper
O. R. Mapper

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

andreask
andreask

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

Moelli.de
Moelli.de

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

Related Questions