locked
Binding to form width RRS feed

  • Question

  • Hi there,

    I would like to bind the width of an object to the form whenever I click a button (so it has to be in code behind)...

    What I have is this:

    DependencyProperty dpWidth = Object.WidthProperty;
    Binding bindActualWidth = new Binding("ActualWidth");
    bindActualWidth.Source = this;
    BindingOperations.SetBinding(ObjectName, dpWidth, bindActualWidth);

    Firstly, this works ok (unless you know of a better, more optimized way of doing it, no problem there)... however what I would like to do is bind to form.ActualWidth - 30...

    Can this be done? how?

    Thanks in advance

    PS: Margin won't work for this case...

    Tuesday, April 14, 2009 8:45 PM

Answers

  • Use a converter (a class that implement IValueConverter), but in a broader sense, you might find you are looking at this the wrong way. Most controls (anything deriving from FrameworkElement) have properties such as HorizontalAlignment to do this kind of thing (and which should work with margins).
    When I first started playing around with WPF, I did things like trying to bind width of controls to the ActualWidth of something else because I didn't really understand how the layout worked.
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 9:02 PM
  • Hi, Rui.

    Let`s implement converter for that binding:

    public class WidthConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                double delta = System.Convert.ToDouble(parameter);
                return (double)value - delta;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }

    and after that we attach converter to binding:

                bindActualWidth.Converter = new WidthConverter();
                bindActualWidth.ConverterParameter = 30;
    


    Hope, this helps.

    • Proposed as answer by Alexander Yudakov Tuesday, April 14, 2009 9:09 PM
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 9:09 PM
  • If the Window form has a name you should use Binding.ElementName property instead of Binding.Source:

    DependencyProperty dpWidth = Object.WidthProperty;
    Binding bindActualWidth = new Binding("ActualWidth");
    bindActualWidth.ElementName = yourWindowName;
    BindingOperations.SetBinding(ObjectName, dpWidth, bindActualWidth);

    Other posibility if the window hasn't a name is use RelativeSource:

    DependencyProperty dpWidth = Object.WidthProperty;
    Binding bindActualWidth = new Binding("ActualWidth");
    bindActualWidth.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType = typeof(Window) };
    BindingOperations.SetBinding(ObjectName, dpWidth, bindActualWidth);
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 11:13 PM

All replies

  • Use a converter (a class that implement IValueConverter), but in a broader sense, you might find you are looking at this the wrong way. Most controls (anything deriving from FrameworkElement) have properties such as HorizontalAlignment to do this kind of thing (and which should work with margins).
    When I first started playing around with WPF, I did things like trying to bind width of controls to the ActualWidth of something else because I didn't really understand how the layout worked.
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 9:02 PM
  • Hi, Rui.

    Let`s implement converter for that binding:

    public class WidthConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                double delta = System.Convert.ToDouble(parameter);
                return (double)value - delta;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }

    and after that we attach converter to binding:

                bindActualWidth.Converter = new WidthConverter();
                bindActualWidth.ConverterParameter = 30;
    


    Hope, this helps.

    • Proposed as answer by Alexander Yudakov Tuesday, April 14, 2009 9:09 PM
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 9:09 PM
  • If the Window form has a name you should use Binding.ElementName property instead of Binding.Source:

    DependencyProperty dpWidth = Object.WidthProperty;
    Binding bindActualWidth = new Binding("ActualWidth");
    bindActualWidth.ElementName = yourWindowName;
    BindingOperations.SetBinding(ObjectName, dpWidth, bindActualWidth);

    Other posibility if the window hasn't a name is use RelativeSource:

    DependencyProperty dpWidth = Object.WidthProperty;
    Binding bindActualWidth = new Binding("ActualWidth");
    bindActualWidth.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType = typeof(Window) };
    BindingOperations.SetBinding(ObjectName, dpWidth, bindActualWidth);
    • Marked as answer by RuiLopes Wednesday, April 15, 2009 10:19 AM
    Tuesday, April 14, 2009 11:13 PM
  • Many thanks for your inputs...

    Looking at all your answers, I ended up following wjousts advice (I reformulated the layout and it worked great and with simpler code - both XAML and code behind)

    Still Mariano's answer improved the binding code and Alexander's provided the right response to this problem...

    So.. I'll classify all of them as answered...

    Many thanks for all answers
    Wednesday, April 15, 2009 10:18 AM