在WPF中有时会用到获取控件的ActualHeight,从而进行相关运算,我是需要在一个UniformGrid中动态的添加Button,然后获取 Button的ActualHeight和相对于UniformGrid的坐标。测试项目代码如下(VS2010):
XAML部分:
- <Window x:Class="WpfApplication2.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainWindow" Height="450" Width="525">
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition/>
- </Grid.ColumnDefinitions>
- <Grid.RowDefinitions>
- <RowDefinition Height="*"/>
- <RowDefinition Height="5*"/>
- </Grid.RowDefinitions>
- <Button Name="btnTest" Grid.Column="0" Grid.Row="0" Height="50" Click="btnTest_Click">TestHeight</Button>
- <UniformGrid Name="ufg" Height="300" Grid.Row="1" Margin="0,21">
- </UniformGrid>
- </Grid>
- </Window>
C#部分:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- namespace WpfApplication2
- {
-
-
-
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- }
- private void btnTest_Click(object sender, RoutedEventArgs e)
- {
- this.ufg.Children.Clear();
- for (int i = 0; i < 20; i++)
- {
- Button btn = new Button();
- btn.Content = i.ToString();
- btn.Click += new RoutedEventHandler(btn_Click);
- this.ufg.Children.Add(btn);
- }
- Button b;
- GeneralTransform transform;
- Point thePoint;
- b = ufg.Children[10] as Button;
- MessageBox.Show("Before UpdateUniformGrid Children[10].ActualHeight:{0}",
- b.ActualHeight.ToString());
- transform = b.TransformToAncestor(ufg);
- thePoint = transform.Transform(new Point(0, 0));
- MessageBox.Show("Before UpdateUniformGrid the Point.Y relative to UniformGrid of Children[10](TransformToAncestor): {0}",
- thePoint.Y.ToString());
- MessageBox.Show("Before UpdateUniformGrid the Point.Y relative to UniformGrid of Children[10](TranslatePoint):{0}",
- b.TranslatePoint(new Point(0, 0), ufg).Y.ToString());
- ufg.UpdateLayout();
- MessageBox.Show("After UpdateUniformGrid Children[10].ActualHeight:{0}",
- b.ActualHeight.ToString());
- transform = b.TransformToAncestor(ufg);
- thePoint = transform.Transform(new Point(0, 0));
- MessageBox.Show("After UpdateUniformGrid, the Point.Y relative to UniformGrid of Children[10](TransformToAncestor):{0}" ,
- thePoint.Y.ToString());
- MessageBox.Show("After UpdateUniformGrid, the Point.Y relative to UniformGrid of Children[10](TranslatePoint):{0}",
- b.TranslatePoint(new Point(0, 0), ufg).Y.ToString());
- }
-
- private void btn_Click(object sender, EventArgs e)
- {
- MessageBox.Show((sender as Button).ActualHeight.ToString());
- Button b = sender as Button;
- MessageBox.Show("the Point.Y relative to UniformGrid:{0}",
- b.TranslatePoint(new Point(0, 0), ufg).Y.ToString());
- }
-
- }
- }
运行一下测试项目就会发现在UpdataLayout之前是得不到ActualHeight 的,但是可以得到相对坐标,而在UpdataLayout之后就可以得到ActualHeight和相对坐标。网上说WPF控件需要在Render之后才能得到ActualHeight,而UpdataLayout应该就有这个功能吧,初接触WPF,所以具体的原理还不太清楚。
另外一个是在获取相对坐标的时,在for循环外的btnTest_Click事件中和在UniformGrid中的按钮单击事件中,使用TransformToAncestor,或TranslatePoint的方法才能得到,其实获取控件的相对坐标还有其他方法,在此不一一列出,需要的朋友可以Google一下。
附件下载(2010项目)
WPF中提供了多种布局方式,因此在布局中的定位相对于WinForm的绝对定位要灵活的多,在WPF中,控件均没有如WinForm中的Location属性,但是,对应的提供了各种设定与获取相对于承载元素的定位
一般来说,Wpf中的布局控件大多都是相对定位(网格,流式,面板等),如果我们要改变控件在布局中的位置可以用Margin,Padding等类似HTML中的方式,虽然说这种方式在WinForm也可用,但是WPF中的布局方式与灵活性已经更接近与HTML了
WPF中也保留了相对传统的布局方式,如在Canvas容器中可以用SetLeft(),SetTop()来绝对定位
关于控件定位详细具体可参考 http://msdn.microsoft.com/zh-cn/library/ms751709.aspx
下来我们来简单描述几种获取控件位置的方式,这也是很多新手容易纠结的地方
1.获取鼠标在控件中的坐标
1 //在Mouse相关的事件中的方式
2 void item_MouseDown(object sender, MouseButtonEventArgs e)
3 {
4 Point point = e.GetPosition(canvas);
5 }
6
7 //或者Mouse的静态方法GetPosition() 获取与指定元素相对的鼠标位置=>等同于上面
8 Point point = Mouse.GetPosition(canvas);
2.获取控件相对于另一控件的坐标
//将相对于此元素的某个点转换至相对于指定元素的坐标中
void item_MouseDown(object sender, MouseButtonEventArgs e)
{
Rectangle rectangle =sender as Rectangle;
Point point = rectangle.TranslatePoint(new Point(),canvas);
}
<strong>
void item_MouseDown( object sender, MouseButtonEventArgs e)
{
Rectangle rectangle =sender as Rectangle;
Point point = rectangle.TranslatePoint( new Point(),canvas);
}
</strong>
|
3.获取控件在Window中的坐标
Window window = Window.GetWindow(canvas);
Point point = canvas.TransformToAncestor(window).Transform(new Point(0, 0));
另外,c#中还提供了控件坐标与屏幕坐标之间的转换,PointFromScreen,PointToScreen,这些就不再一一说明了
总之,根据实际情况选择最适合的方式来获取控件坐标或定位Posts - 3 Articles - 0 Comments - 0 此段示例在MSDN中可见。XAML代码如下:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Margin="16">
<StackPanel Margin="8">
<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />
</StackPanel>
</StackPanel>
</Window>
1、如果只需要获取相对于其父级的偏移量,则可以使用以下方法:
// Return the offset vector for the TextBlock object.
Vector vector = VisualTreeHelper.GetOffset(myTextBlock);
// Convert the vector to a point value.
Point currentPoint = new Point(vector.X, vector.Y);
偏移量保存在Vector对象中
2、相对灵活的方法可以使用 TransformToAncestor方法,这样可以获得相对于Window的偏移量
// Return the general transform for the specified visual object.
GeneralTransform generalTransform1 = myTextBlock.TransformToAncestor(this);
// Retrieve the point value relative to the parent.
Point currentPoint = generalTransform1.Transform(new Point(0, 0));