Size a TextBlock to a Button that changes Width dynamically

…衆ロ難τιáo~ 提交于 2020-01-14 05:27:07

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/1755266/size-a-textblock-to-a-button-that-changes-width-dynamically

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!