dragoncmd
dragoncmd

Reputation: 234

Changing a bound value in xaml

I'm wondering if there's a way to bind the property of one element to another's but modify the data in between. For example could I have a textblock's FontSize be bound to the Window's width/20 or something similar? I've come across areas where this would be useful a few times now, but have always found workarounds (usually involving adding fields to my viewModel). A completely xaml solution is preferred.

Upvotes: 1

Views: 238

Answers (2)

sa_ddam213
sa_ddam213

Reputation: 43606

You can use IValueConverters to handle logic like this.

Here is a example with the scenario you mentioned, You can bind to the window width and use the Converter to divide the width by the value supplied in the ConverterParameter

public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null && parameter != null)
        {
            double divisor = 0.0;
            double _val = 0.0;
            if (double.TryParse(value.ToString(), out _val) && double.TryParse(parameter.ToString(), out divisor))
            {
                return _val / divisor;
            }
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

Xaml:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:converters="clr-namespace:WpfApplication7"
        Title="MainWindow" Height="124" Width="464" Name="YourWindow" >

    <Window.Resources>
        <converters:MyConverter x:Key="MyConverter" />
    </Window.Resources>

    <StackPanel>
        <TextBlock FontSize="{Binding ElementName=YourWindow, Path=ActualWidth, Converter={StaticResource MyConverter}, ConverterParameter=20}" />
    </StackPanel>
</Window>

Upvotes: 0

Shlomo
Shlomo

Reputation: 14350

Yes, by implementing IValueConverter.

Your scenario would look something like this for the converter:

[ValueConversion(typeof(double), typeof(double))]
public class DivideBy20Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var f = (double) value;
        return f/20.0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var f = (double)value;
        return f * 20.0;
    }
}

... and something like this in XAML:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:wpfApplication3="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525"
        x:Name="Window">
    <Window.Resources>
        <wpfApplication3:DivideBy20Converter x:Key="converter"></wpfApplication3:DivideBy20Converter>        
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBox FontSize="{Binding ElementName=Window, Path=Width, Converter={StaticResource converter}}"></TextBox>
    </Grid>
</Window>

Upvotes: 1

Related Questions