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