谁能告诉我如何在Grid控件的给定行/列中居中多边形对象?
我尝试过的例子来自msdn。
<Grid x:Name="LayoutRoot" >
<Polygon Points="300,200 400,125 400,275 300,200"
Stroke="Purple"
StrokeThickness="2"
HorizontalAlignment="Center"
VerticalAlignment="Center" >
<Polygon.Fill>
<SolidColorBrush Color="Blue" Opacity="0.4" />
</Polygon.Fill>
</Polygon>
干杯,
还
添加属性: -
HorizontalAlignment="Center" VerticalAlignment="Center"
到Polygon
。
尽管多边形的边界隐含了高度和宽度,但它默认为容器的大小。
如果你只是设置
HorizontalAlignment="Center" VerticalAlignment="Center"
它将多边形的左上角定位在中心。
您还必须明确设置多边形的高度和宽度以使其居中并保留其边界
添加了尺寸的样本多边形Xaml:
<Grid x:Name="LayoutRoot">
<Path Data="M0.5,41.5 L201,0.5 L302,115 L157.25,157 z" Fill="#FFF4F4F5" Stroke="Black" UseLayoutRounding="False" HorizontalAlignment="Center" VerticalAlignment="Center" Width="302.5" Height="157.5"/>
</Grid>
也许this answer也适用于此。
它使用CenterConverter
public class CenterConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue)
{
return DependencyProperty.UnsetValue;
}
double width = (double) values[0];
double height = (double)values[1];
return new Thickness(-width/2, -height/2, 0, 0);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并将其绑定在XAML中
<Canvas>
<TextBlock x:Name="txt" Canvas.Left="40" Canvas.Top="40" TextAlignment="Center" Text="MMMMMM">
<TextBlock.Margin>
<MultiBinding Converter="{StaticResource centerConverter}">
<Binding ElementName="txt" Path="ActualWidth"/>
<Binding ElementName="txt" Path="ActualHeight"/>
</MultiBinding>
</TextBlock.Margin>
</TextBlock>
<Rectangle Canvas.Left="39" Canvas.Top="39" Width="2" Height="2" Fill="Red"/>
</Canvas>
为了能够在C#中使用它,而不仅仅是在XAML中,你需要这个类
public class Mover : DependencyObject
{
public static readonly DependencyProperty MoveToMiddleProperty =
DependencyProperty.RegisterAttached("MoveToMiddle", typeof (bool), typeof (Mover),
new PropertyMetadata(false, PropertyChangedCallback));
public static void SetMoveToMiddle(UIElement element, bool value)
{
element.SetValue(MoveToMiddleProperty, value);
}
public static bool GetMoveToMiddle(UIElement element)
{
return (bool) element.GetValue(MoveToMiddleProperty);
}
private static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element == null)
{
return;
}
if ((bool)e.NewValue)
{
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = new CenterConverter();
multiBinding.Bindings.Add(new Binding("ActualWidth") {Source = element});
multiBinding.Bindings.Add(new Binding("ActualHeight") {Source = element});
element.SetBinding(FrameworkElement.MarginProperty, multiBinding);
}
else
{
element.ClearValue(FrameworkElement.MarginProperty);
}
}
}
像这样在XAML中使用它
<Canvas>
<TextBlock Canvas.Left="40" Canvas.Top="40" TextAlignment="Center" Text="MMMMMM"
local:Mover.MoveToMiddle="True"/>
</Canvas>
或者像C#那样
Mover.SetMoveToMiddle(UIElement, true);
或者你可以操纵RenderTransform
另一种方法是绑定到RenderTransform而不是Margin。在这种情况下,转换器将返回
return new TranslateTransform(-width / 2, -height / 2);
附加属性的回调方法将包含以下行:
if ((bool)e.NewValue)
{
...
element.SetBinding(UIElement.RenderTransformProperty, multiBinding);
}
else
{
element.ClearValue(UIElement.RenderTransformProperty);
}
此替代方案的优点是附加属性的效果在Visual Studio设计器中可见(在设置Margin属性时不是这种情况)。
在XAML中,这将是这样的:
<Canvas>
<TextBlock x:Name="txt" Canvas.Left="40" Canvas.Top="40" TextAlignment="Center" Text="MMMMMM">
<TextBlock.RenderTransform>
<MultiBinding Converter="{StaticResource centerConverter}">
<Binding ElementName="txt" Path="ActualWidth"/>
<Binding ElementName="txt" Path="ActualHeight"/>
</MultiBinding>
</TextBlock.RenderTransform>
</TextBlock>
<Rectangle Canvas.Left="39" Canvas.Top="39" Width="2" Height="2" Fill="Red"/>
</Canvas>
TextBlock
是对原始答案的质疑。这种方式应该适用于类UIElement
的所有对象。
注意:所有信用都归到上述链接答案的原始海报