UserControl定位理解
UserControl positioning understanding
我越来越接近对 System.Windows.Controls.UserControl
对象定位的理解:
默认情况下,它们没有相对于其容器的 X 或 Y 坐标,但可以使用所谓的“附加属性”添加一些坐标。
这种附加属性的典型示例是 Canvas.Left
和 Canvas.Top
,这意味着,如果 UserControl
的容器是 Canvas
,则以下情况发生(假设) 其左上点(伪代码):
UserControl_UpperLeft_Point.X = Canvas.Left
UserControl_UpperLeft_Point.Y = Canvas.Top
现在我想知道的是:
我的想法对吗?确实是左上角被用了?
如果我想修改这个行为呢,让我们说成:
int left_Margin = 100;
int top_Margin = 200;
UserControl_UpperLeft_Point.X = Canvas.Left / 2 + left_Margin;
UserControl_UpperLeft_Point.Y = Canvas.Top * 2 + top_Margin;
如果我想把我的UserControl
放在右上角甚至中心位置怎么办?
如果您想将控件放置在容器内,您应该遵循 WPF 方式。
水平和垂直对齐并设置边距,就是这样。
<Grid>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="Background" Value="Red" />
<Setter Property="TextElement.Foreground" Value="White" />
<Setter Property="TextElement.FontWeight" Value="Bold" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="TextAlignment" Value="Center" />
</Style>
</Grid.Resources>
<!--#region top-->
<Border
Margin="20,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,20,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,20,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region center-->
<Border
Margin="20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,0,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region bottom-->
<Border
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Right</TextBlock>
</Border>
<Border
Margin="0,0,0,20"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="20,0,0,20"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Left</TextBlock>
</Border>
<!--#endregion-->
</Grid>
如果你想要 old 样式(从 WinForms 中知道你可以对齐它 HorizontalAlignemnt="Top"
和 VerticalAlignment="Left"
并使用 Left
和 Margin
的 Top
属性 设置旧学校 Left
和 Top
.
Is my idea correct? Is it indeed the upper left corner which is used?
在这种情况下有效左上角,但实际上每个边都是对齐的。此外,控件由 Canvas
对齐,它没有设置内部 X 或 Y 坐标。它们由特定于 Canvas
的附加属性给出,没有其他面板。 Canvas
在内部计算绘制 UserControl
.
的矩形
-
Gets or sets a value that represents the distance between the left side of an element and the left side of its parent Canvas.
-
Gets or sets a value that represents the distance between the top of an element and the top of its parent Canvas.
同样重要的是要注意,附加属性有一个 priority。
If you specify them, the attached properties Canvas.Top or Canvas.Left take priority over Canvas.Bottom or Canvas.Right.
What if I want to modify this behaviour, let's say into: [...]
您仍然需要分配附加属性,但之前计算表达式。
- 将
Binding
或 MultiBinding
与自定义值转换器一起使用,以评估作为转换器参数绑定或传递的表达式,或与专用值转换器一起计算特定项。
- 创建您自己的专用附加属性,在内部将计算值分配给
Canvas
个附加属性。
What if I want to position my UserControl, based on the upper right corner
改为设置 Canvas.Top
和 Canvas.Right
附加属性。
<Canvas>
<local:MyUserControl Canvas.Top="0" Canvas.Right="0" Width="50" Height="80"/>
</Canvas>
[...] or even the center?
A Canvas
用于绝对定位。如果你想居中控制,Grid
可能是更好的选择。如果您仍想使用 Canvas
并且它是固定大小,只需自己计算中心坐标并相应地设置附加属性即可。如果它可以调整大小并且 UserControl
位置的位置需要对此做出响应,您可以执行以下操作之一。
在Canvas
周围放一个Grid
,在之后放UserControl
。它会出现在 Canvas
的顶部,并且会自动居中,即使在调整大小时也是如此。
Grid>
<Canvas>
<Rectangle Canvas.Top="80" Canvas.Left="20" Fill="Black" Width="50" Height="50"/>
<Rectangle Canvas.Top="300" Canvas.Left="230" Fill="Black" Width="100" Height="80"/>
</Canvas>
<local:MyUserControl Width="50" Height="80"/>
</Grid>
使用 Canvas
的绑定 ActualSize
来设置附加属性,实现自定义行为或与转换器的复杂绑定,我 不推荐.
我认为对于你的最后一个问题,询问 为什么 你需要这种行为,你想要实现什么 更有用。通常有更简单、更合适的解决方案。
我越来越接近对 System.Windows.Controls.UserControl
对象定位的理解:
默认情况下,它们没有相对于其容器的 X 或 Y 坐标,但可以使用所谓的“附加属性”添加一些坐标。
这种附加属性的典型示例是 Canvas.Left
和 Canvas.Top
,这意味着,如果 UserControl
的容器是 Canvas
,则以下情况发生(假设) 其左上点(伪代码):
UserControl_UpperLeft_Point.X = Canvas.Left
UserControl_UpperLeft_Point.Y = Canvas.Top
现在我想知道的是:
我的想法对吗?确实是左上角被用了?
如果我想修改这个行为呢,让我们说成:
int left_Margin = 100; int top_Margin = 200; UserControl_UpperLeft_Point.X = Canvas.Left / 2 + left_Margin; UserControl_UpperLeft_Point.Y = Canvas.Top * 2 + top_Margin;
如果我想把我的
UserControl
放在右上角甚至中心位置怎么办?
如果您想将控件放置在容器内,您应该遵循 WPF 方式。
水平和垂直对齐并设置边距,就是这样。
<Grid>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="Background" Value="Red" />
<Setter Property="TextElement.Foreground" Value="White" />
<Setter Property="TextElement.FontWeight" Value="Bold" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="TextAlignment" Value="Center" />
</Style>
</Grid.Resources>
<!--#region top-->
<Border
Margin="20,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,20,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,20,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region center-->
<Border
Margin="20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,0,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region bottom-->
<Border
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Right</TextBlock>
</Border>
<Border
Margin="0,0,0,20"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="20,0,0,20"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Left</TextBlock>
</Border>
<!--#endregion-->
</Grid>
如果你想要 old 样式(从 WinForms 中知道你可以对齐它 HorizontalAlignemnt="Top"
和 VerticalAlignment="Left"
并使用 Left
和 Margin
的 Top
属性 设置旧学校 Left
和 Top
.
Is my idea correct? Is it indeed the upper left corner which is used?
在这种情况下有效左上角,但实际上每个边都是对齐的。此外,控件由 Canvas
对齐,它没有设置内部 X 或 Y 坐标。它们由特定于 Canvas
的附加属性给出,没有其他面板。 Canvas
在内部计算绘制 UserControl
.
-
Gets or sets a value that represents the distance between the left side of an element and the left side of its parent Canvas.
-
Gets or sets a value that represents the distance between the top of an element and the top of its parent Canvas.
同样重要的是要注意,附加属性有一个 priority。
If you specify them, the attached properties Canvas.Top or Canvas.Left take priority over Canvas.Bottom or Canvas.Right.
What if I want to modify this behaviour, let's say into: [...]
您仍然需要分配附加属性,但之前计算表达式。
- 将
Binding
或MultiBinding
与自定义值转换器一起使用,以评估作为转换器参数绑定或传递的表达式,或与专用值转换器一起计算特定项。 - 创建您自己的专用附加属性,在内部将计算值分配给
Canvas
个附加属性。
What if I want to position my UserControl, based on the upper right corner
改为设置 Canvas.Top
和 Canvas.Right
附加属性。
<Canvas>
<local:MyUserControl Canvas.Top="0" Canvas.Right="0" Width="50" Height="80"/>
</Canvas>
[...] or even the center?
A Canvas
用于绝对定位。如果你想居中控制,Grid
可能是更好的选择。如果您仍想使用 Canvas
并且它是固定大小,只需自己计算中心坐标并相应地设置附加属性即可。如果它可以调整大小并且 UserControl
位置的位置需要对此做出响应,您可以执行以下操作之一。
在
Canvas
周围放一个Grid
,在之后放UserControl
。它会出现在Canvas
的顶部,并且会自动居中,即使在调整大小时也是如此。Grid> <Canvas> <Rectangle Canvas.Top="80" Canvas.Left="20" Fill="Black" Width="50" Height="50"/> <Rectangle Canvas.Top="300" Canvas.Left="230" Fill="Black" Width="100" Height="80"/> </Canvas> <local:MyUserControl Width="50" Height="80"/> </Grid>
使用
Canvas
的绑定ActualSize
来设置附加属性,实现自定义行为或与转换器的复杂绑定,我 不推荐.
我认为对于你的最后一个问题,询问 为什么 你需要这种行为,你想要实现什么 更有用。通常有更简单、更合适的解决方案。