动态更改内容时,客户控件的内容实际大小始终返回0

时间:2019-01-23 16:16:32

标签: c# uwp custom-controls

在我的控件中,其内容呈现器位于画布面板内。我已经根据内容的实际大小安排了((在屏幕上的中心对齐,在屏幕上指向左,右)在画布上的内容。正确加载了初始内容的大小,并且在动态更改内容时,它的实际大小始终返回0。因此,可以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 :(得分:1)

问题是因为您太早访问它的大小,甚至没有在XAML页面上呈现它。您可能会问为什么网格第一次在XAML页面上具有大小。这是因为父面板在布局其子元素时已经执行了此操作(类似于Measure(size))。

因此,要解决您的问题,您可以注册“ CustomLabel”的LayoutUpdated事件。然后,可以在其事件处理程序中调用CalculateContentPosition()方法,而不用调用OnContentChanged方法。

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

private void CustomLabel_LayoutUpdated(object sender, object e)
{
    CalculateContentPosition();
}