2011-09-12 36 views
7

TextBlock應居中位置x(或方向垂直時爲y)。 我實現:如何將TextBlock居中到指定的位置

TextBlock text = new TextBlock(); 
// Some code to define text, font, etc. here 

// Turn if Orientation is vertical 
if (Orientation == Orientation.Vertical) 
{ 
    text.RenderTransform = new RotateTransform() { Angle = 270 }; 
} 

// Update, then ActualWidth is set correctly 
text.UpdateLayout(); 

// Position of label centered to given position 
double halfWidth = text.ActualWidth/2; 
double x1 = (Orientation == Orientation.Horizontal) ? x - halfWidth : x; 
double y1 = (Orientation == Orientation.Horizontal) ? y : y + halfWidth; 

Canvas.SetLeft(text, x1); 
Canvas.SetTop(text, y1); 

Children.Add(text); // Add to Canvas 

這工作實際罰款,但有可能做到這一點不UpdateLayout。如果我刪除UpdateLayout,那麼我沒有找到我正在尋找的位置,因爲ActualWidth(當然)是零。

+1

你知道,如果你使用一個網格,容器,你要馬上把它居中?除此之外:嘗試使用LayoutTransform而不是RenderTransform – fixagon

+0

父控件是什麼?這段代碼的上下文是什麼? – loxxy

+0

@fantasticfix我必須使用RenderTransform,因爲它在WPF和Silverlight中運行。 SL不知道LayoutTransform。 – Em1

回答

3

你也許可以做到這一點通過Canvas.Top/Canvas.Left值綁定到TextBlock的ActualWidth/ActualHeight和使用Converter

下面是一個例子。我使用通常用於數學公式的自定義MathConverter(代碼可以找到here),但是您也可以使用普通轉換器,該轉換器返回所傳遞值的一半。

<Style TargetType="{x:Type TextBlock}"> 
    <Style.Triggers> 
     <Trigger Property="Orientation" Value="Horizontal"> 
      <Setter Property="Canvas.Left" 
        Value="{Binding RelativeSource={RelativeSource Self}, 
        Path=ActualWidth, 
        Converter={StaticResource MathConverter}, 
        [email protected]/2}" /> 
     </Trigger> 
     <Trigger Property="Orientation" Value="Vertical"> 
      <Setter Property="Canvas.Top" 
        Value="{Binding RelativeSource={RelativeSource Self}, 
        Path=ActualHeight, 
        Converter={StaticResource MathConverter}, 
        [email protected]/2}" /> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

編輯

只是重新閱讀的問題,並意識到你正在試圖在特定的X居中的TextBlock,Y在畫布上的座標。在這種情況下,你需要實現一個MultiConverter而不是一個普通的Converter,這樣你就可以傳遞兩個參數:X/Y值和ActualHeight/ActualWidth值

+0

好主意。我會試一試。 – Em1

+0

工作正常,謝謝。 – Em1

0

我假設你編寫了這段代碼構造函數。這將是ActualWidth沒有價值的原因。 所有代碼未經測試(沒有IDE可用)。在WPF構建佈局之後,您需要在加載事件之後執行此操作。這是一個路由事件,順便說一句。

public class Class1{ 
public Class1() 
{ 
    this.Loaded += (sender, args) => 
    { 
     TextBlock text = new TextBlock(); 

     if (Orientation == Orientation.Vertical) 
     { 
      text.RenderTransform = new RotateTransform() { Angle = 270 }; 
     } 

     double halfWidth = text.ActualWidth/2; 
     double x1 = (Orientation == Orientation.Horizontal) ? x - halfWidth : x; 
     double y1 = (Orientation == Orientation.Horizontal) ? y : y + halfWidth; 

     Canvas.SetLeft(text, x1); 
     Canvas.SetTop(text, y1); 
     Children.Add(text); 
    }; 
} 

此代碼可能會工作。當然,按照我讀取代碼的方式,這段代碼似乎位於從Canvas派生的類的構造函數中。除非您確實需要擴展畫布控件的核心功能,否則通常不需要這樣做。您可以通過創建UserControl在現有控件上創建可重用組件。如果您不需要重寫Canvas的任何方法,則應特別使用此方法。

或者,如果你只是想有一個容器內的中心項目,下面的XAML將這樣做就好了:

 <Grid> 
     <TextBlock Text="Haha!" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
    </Grid> 
+1

我不認爲這會工作,因爲我相信你需要呈現一個控制,然後才能得到它'ActualWidth' – Rachel

+0

不是構造函數。 Horizo​​ntalAlignment不適用於我。 – Em1

+0

@Rachel:沒錯。這就是爲什麼我們應該嘗試獲取加載事件後的實際寬度。 –

相關問題