Flack
Flack

Reputation: 5899

Binding a custom dependency property to the Width of a control

I have a user control that contains the following element:

        <Border x:Name="border" BorderThickness="1">
            <StackPanel Orientation="Horizontal">
                <CheckBox Margin="5"></CheckBox>
                <TextBox Width="100" Margin="5"/>
            </StackPanel>
        </Border>

In the code behind of this user control I have a custom dependency property:

        public static readonly DependencyProperty BorderWidthProperty = DependencyProperty.Register("BorderWidth", typeof(int), typeof(TestControl));
        public int BorderWidth
        {
            get { return (int)base.GetValue(BorderWidthProperty); }
            set { base.SetValue(BorderWidthProperty, value); }
        }

What I am trying to do is have the BorderWidth property always be equal to the Width of the border control.

I tried adding the following binding, thinking that OneWayToSource was what I needed, where myControl is the name of the user control the border is contained in:

<UserControl x:Class="Sandbox.TestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             x:Name="myControl">

<Border x:Name="border" Width="{Binding ElementName=myControl, Path=BorderWidth, Mode=OneWayToSource}">

But I get the following exception:

System.Windows.Data Error: 7 : ConvertBack cannot convert value 'NaN' (type 'Double'). BindingExpression:Path=BorderWidth; DataItem='TestControl' (Name='myControl'); target element is 'Border' (Name='border'); target property is 'Width' (type 'Double') OverflowException:'System.OverflowException: Value was either too large or too small for an Int32.
   at System.Convert.ToInt32(Double value)
   at System.Double.System.IConvertible.ToInt32(IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
   at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'

What I am trying to do is have the Width of the border be controlled as usual by the layout system but always have the BorderWidth property equal to the borders Width. It looks like the Width of the border element is not defined when it tries to update BorderWidth.

Also, is the BorderWidth property required to be a dependency property for this to work?

Thanks.

Upvotes: 0

Views: 4413

Answers (2)

alpha-mouse
alpha-mouse

Reputation: 5003

You should rather use FrameworkElement.ActualWidth property.

EDIT: See the comment below. this approach doesn't work.

Upvotes: 0

Flack
Flack

Reputation: 5899

I ended up changing my approach. I added a property to my user control that was updated whenever the size of the border changed (listening to the border's SizeChanged event). The user control implements INotifyPropertyChanged and anyone interested in BorderWidth would now always get back the ActualWidth of the border element:

        double _borderWidth;
        public double BorderWidth
        {
            get
            {
                return _borderWidth;
            }
            set
            {
                _borderWidth= value;
                this.OnPropertyChanged("BorderWidth");
            }
        }

        private void Border_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            BorderWidth = border.ActualWidth;
        }

Upvotes: 1

Related Questions