在WPF中有時(shí)會(huì)用到獲取控件的ActualHeight,從而進(jìn)行相關(guān)運(yùn)算,我是需要在一個(gè)UniformGrid中動(dòng)態(tài)的添加Button,然后獲取 Button的ActualHeight和相對(duì)于UniformGrid的坐標(biāo)。測(cè)試項(xiàng)目代碼如下(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());
- }
-
- }
- }
運(yùn)行一下測(cè)試項(xiàng)目就會(huì)發(fā)現(xiàn)在UpdataLayout之前是得不到ActualHeight 的,但是可以得到相對(duì)坐標(biāo),而在UpdataLayout之后就可以得到ActualHeight和相對(duì)坐標(biāo)。網(wǎng)上說(shuō)WPF控件需要在Render之后才能得到ActualHeight,而UpdataLayout應(yīng)該就有這個(gè)功能吧,初接觸WPF,所以具體的原理還不太清楚。
另外一個(gè)是在獲取相對(duì)坐標(biāo)的時(shí),在for循環(huán)外的btnTest_Click事件中和在UniformGrid中的按鈕單擊事件中,使用TransformToAncestor,或TranslatePoint的方法才能得到,其實(shí)獲取控件的相對(duì)坐標(biāo)還有其他方法,在此不一一列出,需要的朋友可以Google一下。
附件下載(2010項(xiàng)目)
WPF中提供了多種布局方式,因此在布局中的定位相對(duì)于WinForm的絕對(duì)定位要靈活的多,在WPF中,控件均沒(méi)有如WinForm中的Location屬性,但是,對(duì)應(yīng)的提供了各種設(shè)定與獲取相對(duì)于承載元素的定位
一般來(lái)說(shuō),Wpf中的布局控件大多都是相對(duì)定位(網(wǎng)格,流式,面板等),如果我們要改變控件在布局中的位置可以用Margin,Padding等類(lèi)似HTML中的方式,雖然說(shuō)這種方式在WinForm也可用,但是WPF中的布局方式與靈活性已經(jīng)更接近與HTML了
WPF中也保留了相對(duì)傳統(tǒng)的布局方式,如在Canvas容器中可以用SetLeft(),SetTop()來(lái)絕對(duì)定位
關(guān)于控件定位詳細(xì)具體可參考 http://msdn.microsoft.com/zh-cn/library/ms751709.aspx
下來(lái)我們來(lái)簡(jiǎn)單描述幾種獲取控件位置的方式,這也是很多新手容易糾結(jié)的地方
1.獲取鼠標(biāo)在控件中的坐標(biāo)
1 //在Mouse相關(guān)的事件中的方式
2 void item_MouseDown(object sender, MouseButtonEventArgs e)
3 {
4 Point point = e.GetPosition(canvas);
5 }
6
7 //或者M(jìn)ouse的靜態(tài)方法GetPosition() 獲取與指定元素相對(duì)的鼠標(biāo)位置=>等同于上面
8 Point point = Mouse.GetPosition(canvas);
2.獲取控件相對(duì)于另一控件的坐標(biāo)
//將相對(duì)于此元素的某個(gè)點(diǎn)轉(zhuǎn)換至相對(duì)于指定元素的坐標(biāo)中
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中的坐標(biāo)
Window window = Window.GetWindow(canvas);
Point point = canvas.TransformToAncestor(window).Transform(new Point(0, 0));
另外,c#中還提供了控件坐標(biāo)與屏幕坐標(biāo)之間的轉(zhuǎn)換,PointFromScreen,PointToScreen,這些就不再一一說(shuō)明了
總之,根據(jù)實(shí)際情況選擇最適合的方式來(lái)獲取控件坐標(biāo)或定位Posts - 3 Articles - 0 Comments - 0 此段示例在MSDN中可見(jiàn)。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、如果只需要獲取相對(duì)于其父級(jí)的偏移量,則可以使用以下方法:
// 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對(duì)象中
2、相對(duì)靈活的方法可以使用 TransformToAncestor方法,這樣可以獲得相對(duì)于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));