MCSharp
MCSharp

Reputation: 1068

How can you programatically bind a Double to a WidthProperty?

Can a double or int be bound to a WidthProperty of an element such as a Button or Border?

I have something like this but it does not seem to work. Maybe it's not the Value property that the binding needs.

double changedNum = 3;
double myWidth = 100 * changedNum;
border1.SetBinding(WidthProperty, new Binding("Value") { Source = myWidth });

Update

I have posted an answer to my question. My goal was to bind an existing slider value and multiply or divide by a double. Then have that value set as binding for another object's WidthProperty. Solution is below.

Upvotes: 0

Views: 961

Answers (5)

Mohsen Afshin
Mohsen Afshin

Reputation: 13436

Just like SLacks answer but with anonymous types:

Binding binding = new Binding("SomeProperty");
binding.Source = new {SomeProperty = myLocalVariable};

Upvotes: 0

Karthik
Karthik

Reputation: 991

For Databinding to work, the binding target i.e the Property to which the value is bound needs to be a Dependency property and the binding source needs to be a class Property.

In the below code snippet

<Textbox Text="{Binding MyText}" ... />

The control Textbox has a dependency property called "TextProperty" and MyText has to be a class Property. The reason why MyText needs to be a class property is because behind the scenes WPF/Silverlight looks for the method getMyText() when reading the value to bind to and setMyText() when updating the value. For more information on how binding works behind the scenes I would recommend that one see the implementation of the Binding class in PresenationFramework.dll using dotPeek or some other tool.

Upvotes: 0

MCSharp
MCSharp

Reputation: 1068

My solution was to create a Slider with Visibility="Collapsed" to hide the element. Then I created a ValueChanged event on the object I wanted to multiply the value for. The event would update the hidden Slider Value.

This would allow me to bind the Value with the multiplied double to the desired object such as Border or Button.

Here is a working example.

<Window x:Class="WidthExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" SizeToContent="WidthAndHeight">
    <Grid Margin="10" MinWidth="500" HorizontalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Ellipse Fill="#FFCD4B7A" HorizontalAlignment="Center" Grid.Row="0" VerticalAlignment="Top" Width="{Binding ElementName=mainSlider, Path=Value}" Height="{Binding ElementName=mainSlider, Path=Value}" Margin="0,0,0,10"/>
        <Rectangle Fill="#FFCD6B19" HorizontalAlignment="Center" Grid.Row="1" VerticalAlignment="Top" Width="{Binding ElementName=hiddenWidthSlider, Path=Value}" Height="{Binding ElementName=hiddenHeightSlider, Path=Value}" Margin="0,0,0,10"/>
        <StackPanel Grid.Row="2">
            <Slider x:Name="mainSlider" Value="50" Minimum="10" Maximum="300" SmallChange="1" LargeChange="1" TickPlacement="BottomRight" TickFrequency="5" ValueChanged="mainSlider_ValueChanged" />
            <Slider x:Name="hiddenWidthSlider" Value="50" Minimum="1" Maximum="1000" SmallChange="1" LargeChange="1" Visibility="Collapsed" />
            <Slider x:Name="hiddenHeightSlider" Value="50" Minimum="1" Maximum="1000" SmallChange="1" LargeChange="1" Visibility="Collapsed" />
        </StackPanel>
    </Grid>
</Window>

CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WidthExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void mainSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (hiddenWidthSlider != null)
            {
                hiddenWidthSlider.Value = mainSlider.Value * 2;
            }
            if (hiddenHeightSlider != null)
            {
                hiddenHeightSlider.Value = mainSlider.Value / 2;
            }
        }
    }
}

Here, The Slider controls the Width and Height of the circle. There are two hidden sliders that control the width and height of the Rectangle. The value of the circle is used to base the value of the rectangle.

In this case, the width of the rectangle is twice the width and half the height of the circle. I don't know if using a hidden element is the best solution, but it is an option.

Upvotes: 0

Benjamin
Benjamin

Reputation: 1173

Is your intent to always multiply the bound source value by some constant?

  • Then you may want to use an IValueConverter in your binding OR
  • if you are writing a control code, define your border element as a template part and update the respective property of the template part with the multiplied value each time WidthProperty gets updated.

Otherwise, you could write

double changedNum = 3;
double myWidth = 100 * changedNum;
border1.SetBinding(WidthProperty, new Binding(".") { Source = myWidth });

Upvotes: 0

SLaks
SLaks

Reputation: 887413

You can't bind a local variable.

Instead, you need to bind a property of some object:

someObject.SomeProperty = 42;
new Binding("SomeProperty", someObject)

Upvotes: 3

Related Questions