Фактический размер содержимого элемента управления клиента всегда возвращает 0 при динамическом изменении содержимого - PullRequest
0 голосов
/ 23 января 2019

В моем контроле наличие содержания предъявителя, который внутри панели холста. Я упорядочил ((Выровнять по центру, по левому и правому краю экрана) содержимое холста на основе фактического размера содержимого. Исходный размер содержимого загружается правильно, а при динамическом изменении содержимого его фактический размер всегда возвращает 0. Из-за этого can ' t выровнять контент по положению экрана. Подскажите, пожалуйста, как получить размер контента в динамическом случае, как показано в сценарии ниже

 <Page.Resources>
    <!--control style--> 
    <Style TargetType="local:CustomLabel">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:CustomLabel">
                    <Grid>
                        <Canvas>
                            <Ellipse Height="10" Width="10" Canvas.Left="300" Canvas.Top="300" Fill="Red" />
                        </Canvas>
                        <Canvas>
                            <ContentPresenter Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelMargin}"  Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
                        </Canvas>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>
<Grid>
    <local:CustomLabel x:Name="label">
        <local:CustomLabel.Content>
            <Grid>
                <TextBlock Text="Initial Label" />
            </Grid>
        </local:CustomLabel.Content>
    </local:CustomLabel>
    <Button Content="Change text" VerticalAlignment="Bottom" Height="75" Click="Button_Click" />
</Grid>

public MainPage()
    {
        this.InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var grid = new Grid();
        grid.Children.Add(new TextBlock() { Text = "Change" });
        this.label.Content = grid;
    }

// control implementation 
public class CustomLabel : Control
{
    bool loadTime = false;
    public CustomLabel()
    {
        this.SizeChanged += CustomLabel_SizeChanged;
    }
    private void CustomLabel_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        loadTime = true;
        CalculateContentPosition();
    }
    private void CalculateContentPosition()
    {
        if (loadTime)
        {
            var content = Content as FrameworkElement;
            if (content != null)
            {
                var left = content.ActualWidth / 2;
                var top = content.ActualHeight / 2;
                this.LabelMargin = new Thickness(300 - left, 300 - top, 0, 0);
            }
        }
    }
    public object Content
    {
        get { return (object)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Content.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.Register("Content", typeof(object), typeof(CustomLabel), new PropertyMetadata(null,OnContentChanged));
    private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as CustomLabel).CalculateContentPosition();
    }
    public Thickness LabelMargin
    {
        get { return (Thickness)GetValue(LabelMarginProperty); }
        set { SetValue(LabelMarginProperty, value); }
    }
    // Using a DependencyProperty as the backing store for LabelMargin.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LabelMarginProperty =
        DependencyProperty.Register("LabelMargin", typeof(Thickness), typeof(CustomLabel), new PropertyMetadata(new Thickness(1)));
}

1 Ответ

0 голосов
/ 24 января 2019

Проблема заключалась в том, что вы обращались к его размеру слишком рано, он даже не отображался на странице XAML. Вы можете спросить, почему Grid имеет размер на странице XAML в первый раз. Это потому, что родительская панель выполнила эту операцию (аналогично Measure(size)), когда разметила свои дочерние элементы.

Итак, чтобы решить ваш вопрос, вы можете зарегистрировать событие LayoutUpdated вашей 'CustomLabel'. Затем в его обработчике событий вы могли бы вызвать метод CalculateContentPosition() вместо вызова метода OnContentChanged.

public CustomLabel()
{
    this.SizeChanged += CustomLabel_SizeChanged;
    this.LayoutUpdated += CustomLabel_LayoutUpdated;
}

private void CustomLabel_LayoutUpdated(object sender, object e)
{
    CalculateContentPosition();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...