在网格控件中居中一个多边形

5

请问如何将多边形对象居中于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>

Cheers,

Xam

3个回答

3
添加属性:-
 HorizontalAlignment="Center" VerticalAlignment="Center"

Polygon


0

也许这个答案在这里也适用。

它使用了一个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

注意:以上链接答案的所有功劳归原作者所有。


0

尽管多边形的边界隐含了高度和宽度,但它默认为容器的大小。

如果你只是设置

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>

@HiTechMagic:你是如何定义容器和多边形的?在我看到你的帖子后,我快速尝试了一下简单的网格和四点多边形,但并没有看到它们被拉伸。 - Wonko the Sane
@HiTechMagic:我和Wonko有同样的问题。尽管按照您的指示操作,但我无法使一个简单的多边形(在我的情况下是三角形)居中于网格控件中。 - Xam
@Wonko和Xam:我的错误。默认情况下,我已经在多边形上设置了填充。答案已经更正。基本解决方案仍然相同。确保将大小设置为多边形的边界。干杯! - iCollect.it Ltd
@HiTechMagic:再次感谢。您能否提供一个XAML片段,演示您是如何实现这个结果的? - Xam
@Xam:上面添加了Xaml。看到并纠正你的Xaml会更有用。我的是在Blend中使用钢笔工具编写的简单多边形。 - iCollect.it Ltd
@HiTechMagic:谢谢。我已经添加了上面的样例。 - Xam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接