views:

127

answers:

1

Hi,

I have a TextBlock that's on top of a Button in a Grid. I'd like to have then displayed thus:

"some very long text" <-- text
"that doesn't fit" <-- text wrapped
[my button text size] <-- button

However, what I've got is this:

"some very long text that doesn't fit" <-- text
[my button text size] <-- button

My issue is that the text in the Button is dynamically set through localized resource and therefore the width of the button changes dynamically.

The static solution that works for non-dynamic Button resize is:

                <TextBlock
                    Margin="5"
                    TextWrapping="Wrap"
                    Width="{Binding ElementName=requestDemoButton, Path=RenderSize.Width}"
                    Text="{Binding Path=Resource.Text, Source={StaticResource LocalizedStrings }}"
                    />
                <Button 
                    x:Name="requestDemoButton"
                    Margin="5" 
                    Height="Auto" 
                    Width="Auto" 
                    HorizontalAlignment="Right"
                    Content="{Binding Path=Resource.Button, Source={StaticResource LocalizedStrings }}" />

Ideas, anyone? I'm currently thinking of sticking a Behavior class to the TextBlock that listens for the SizeChanged event on the Button. I'd like to have a built-in solution if it exists.

A: 

If anyone's interested, here's how I've done in in a behaviour. I pass on Height or Width according to the property I want bound.

Here's the class:

public static class DynamicControlResizeBehavior
{
    public static readonly DependencyProperty TargetProperty =
        DependencyProperty.RegisterAttached("Target", typeof(FrameworkElement), typeof(DynamicControlResizeBehavior), new PropertyMetadata(OnTargetSetCallback));

    public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.RegisterAttached("PropertyName", typeof(string), typeof(DynamicControlResizeBehavior), new PropertyMetadata(OnPropertyNameSetCallback));


    public static string GetPropertyName(DependencyObject obj)
    {
        return (string)obj.GetValue(PropertyNameProperty);
    }

    public static void SetPropertyName(DependencyObject obj, string value)
    {
        obj.SetValue(PropertyNameProperty, value);
    }

    public static FrameworkElement GetTarget(DependencyObject obj)
    {
        return (FrameworkElement)obj.GetValue(TargetProperty);
    }

    public static void SetTarget(DependencyObject obj, FrameworkElement value)
    {
        obj.SetValue(TargetProperty, value);
    }

    private static void SynchronizeProperty(DependencyObject dependencyObject)
    {
        var target = GetTarget(dependencyObject);
        if (target != null)
        {
            var propertyName = GetPropertyName(dependencyObject);

            DependencyProperty dependencyToRead;
            DependencyProperty dependencyToWrite;
            if (string.Equals(propertyName, "Width", StringComparison.InvariantCulture))
            {
                dependencyToRead = FrameworkElement.ActualWidthProperty;
                dependencyToWrite = FrameworkElement.WidthProperty;
            }
            else if (string.Equals(propertyName, "Height", StringComparison.InvariantCulture))
            {
                dependencyToRead = FrameworkElement.ActualHeightProperty;
                dependencyToWrite = FrameworkElement.HeightProperty;
            }
            else
            {
                return;
            }

            var propertySize = (double)target.GetValue(dependencyToRead);
            dependencyObject.SetValue(dependencyToWrite, propertySize);
        }
    }

    private static void OnTargetSetCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var oldElement = e.OldValue as FrameworkElement;
        if (oldElement != null)
        {
            oldElement.SizeChanged -= (o, s) => SynchronizeProperty(d);
        }

        var newElement = e.NewValue as FrameworkElement;
        if (newElement != null)
        {
            newElement.SizeChanged += (o, s) => SynchronizeProperty(d);
        }
    }

    private static void OnPropertyNameSetCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SynchronizeProperty(d);
    }
}

And here's how it's used:

            <TextBlock
                Behaviors:DynamicControlResizeBehavior.Target="{Binding ElementName=submitButton}"
                Behaviors:DynamicControlResizeBehavior.PropertyName="Width"
                HorizontalAlignment="Right"
                Margin="5,20,5,5"
                TextWrapping="Wrap"
                Text="{Binding Path=Resource.RequestDemoLoginText, Source={StaticResource LocalizedStrings }}"
                />
            <Button 
                x:Name="submitButton"
                Margin="5" 
                Height="Auto" 
                Width="Auto" 
                HorizontalAlignment="Right"
                HorizontalContentAlignment="Left"
                Content="{Binding Path=Resource.RequestDemoLogin, Source={StaticResource LocalizedStrings }}" />

Hope that might help someone else.

R4cOON