2010-01-10 4 views
15
는 다음 코드

: alt text정렬 바닥


자신의 텍스트 바닥이 있어야 할 수 있도록 내가 레이블 '스타일로 설정할 수있는 방법이 있나요 :

<Window x:Class="Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Grid> 
     <StackPanel Orientation="Horizontal" 
        VerticalAlignment="Center" 
        HorizontalAlignment="Center">    
      <Label Content="Name:"/> 
      <Label Content="Itzhak Perlman" FontSize="44"/> 
     </StackPanel> 
    </Grid> 
</Window> 

은 다음과 렌더링 정렬?
TextBlocks에서도 동일한 질문이 있습니다.

참고 : 잠시 동안이 문제로 어려움을 겪었으므로 그 사실을 알고있는 특정 답변 만 게시하십시오.
이미 시도 : VerticalAlignment, VerticalContentAlignment, Padding, Margin. 내가 알지 못하는 것이 있습니까?

나는 this 게시물을 읽었지만 다른 글꼴 크기의 시나리오에 대해서는 언급하지 않습니다.

업데이트 : 문제는 Padding이 0으로 설정되어 있어도 ContentPresenter 영역 내에서 글꼴 주위에 여전히 불확실한 공간이 있다는 것입니다. 이 공간은 글꼴 크기에 따라 다릅니다. 이 공간을 제어 할 수 있다면 더 나은 상황이 될 것입니다.

감사합니다.

+1

아하! 업데이트로 문제가 명확 해집니다. –

답변

6

XAML 전용 솔루션이 없으므로 코드를 사용해야합니다. 또한 코드 숨김을 사용하더라도 텍스트가 여러 줄이면 무엇 때문에이 문제에 대한 일반적인 해결책은 없습니까? 어떤 기준선을 사용해야합니까? 또는 템플릿에 여러 텍스트 요소가있는 경우 어떻게해야합니까? 헤더와 내용, 또는 그 이후의 기준선은?

요약하면 가장 좋은 방법은 위쪽/아래쪽 여백을 사용하여 수동으로 텍스트를 정렬하는 것입니다.

텍스트 요소가 하나만 있다고 가정하고 싶다면 FormattedText 개체를 기존 요소의 모든 속성으로 인스턴스화하여 요소 위쪽에서 기준선까지의 픽셀 거리를 계산할 수 있습니다 텍스트 요소. FormattedText 개체에는 해당 값을 보유하는 doubleBaseline 속성이 있습니다. 요소가 컨테이너의 상단 또는 하단에 정확히 위치하지 않을 수 있으므로 여백을 수동으로 입력해야합니다. Textbox Baseline

여기에 그 값을 추출 내가 쓴 방법이있다 :

이 MSDN 포럼 게시물을 참조하십시오. 단일 기본 클래스에 공통적이지 않기 때문에 리플렉션을 사용합니다 (이들은 Control, TextBlock, Page, TextElement 및 기타로 별도로 정의됩니다).

public double CalculateBaseline(object textObject) 
{ 
    double r = double.NaN; 
    if (textObject == null) return r; 

    Type t = textObject.GetType(); 
    BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; 

    var fontSizeFI = t.GetProperty("FontSize", bindingFlags); 
    if (fontSizeFI == null) return r; 
    var fontFamilyFI = t.GetProperty("FontFamily", bindingFlags); 
    var fontStyleFI = t.GetProperty("FontStyle", bindingFlags); 
    var fontWeightFI = t.GetProperty("FontWeight", bindingFlags); 
    var fontStretchFI = t.GetProperty("FontStretch", bindingFlags); 

    var fontSize = (double)fontSizeFI.GetValue(textObject, null); 
    var fontFamily = (FontFamily)fontFamilyFI.GetValue(textObject, null); 
    var fontStyle = (FontStyle)fontStyleFI.GetValue(textObject, null); 
    var fontWeight = (FontWeight)fontWeightFI.GetValue(textObject, null); 
    var fontStretch = (FontStretch)fontStretchFI.GetValue(textObject, null); 

    var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch); 

    var formattedText = new FormattedText(
     "W", 
     CultureInfo.CurrentCulture, 
     FlowDirection.LeftToRight, 
     typeFace, 
     fontSize, 
     Brushes.Black); 

    r = formattedText.Baseline; 

    return r; 
} 

EDIT : Shimmy, 귀하의 의견에 대한 답변으로, 나는 당신이 실제로이 솔루션을 사용해 본 것으로 믿지 않습니다.여기

Example Baseline Alignment

XAML 것 : 여기 예제가

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="TextBlock"> 
      <Setter Property="Margin" Value="0,40,0,0"/> 
     </Style> 
    </StackPanel.Resources> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Name="tb1" Text="Lorem " FontSize="10"/> 
     <TextBlock Name="tbref" Text="ipsum"/> 
    </StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Name="tb2" Text="dolor " FontSize="20"/> 
     <TextBlock Text="sit"/> 
    </StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Name="tb3" Text="amet " FontSize="30"/> 
     <TextBlock Text="consectetuer"/> 
    </StackPanel> 
</StackPanel> 

그리고 여기에 그 뒤의 코드는이

double baseRef = CalculateBaseline(tbref); 
double base1 = CalculateBaseline(tb1) - baseRef; 
double base2 = CalculateBaseline(tb2) - baseRef; 
double base3 = CalculateBaseline(tb3) - baseRef; 
tb1.Margin = new Thickness(0, 40 - base1, 0, 0); 
tb2.Margin = new Thickness(0, 40 - base2, 0, 0); 
tb3.Margin = new Thickness(0, 40 - base3, 0, 0); 
+0

@ אביעד,이 값으로 무엇을합니까? 실제로 'BaseLine'은 무엇입니까? – Shimmy

+0

기준선은 텍스트 요소의 맨 위와 모든 문자가 '앉다'는 선 사이의 거리입니다. 예를 들어 'Top'마진을 설정하여 50에서 기본 오프셋을 뺀 값을 지정하면 글꼴 크기에 관계없이 특정 줄로 정렬 할 수 있습니다. –

+0

그게 내가 시도했지만 작동하지 않습니다. 나는 여전히 해결책을 찾고있다. 문제는 여백과 '텍스트 상단'사이의 간격입니다. 내 질문을 업데이트했습니다. 모든 노력을 주셔서 감사합니다. 뉴스가 있으십니까? – Shimmy

0

실제로 Aviad 년대를 기반으로 간단한 대답을 발견 달성의 .

나는 요소 자체를 받아들이고 계산 된 두께를 반환하는 Aviad의 함수가 포함 된 변환기를 만들었습니다.

은 그럼 단점은 TextBlock에 그래서 우리는 TemplateBinding을 통해 설정할 수 없습니다 템플릿을 가지고 있지 않기 때문에이 분명히 원래 여백 속성을 차지한다는 것입니다

<Style TargetType="TextBlock"> 
    <Setter Property="Margin" 
     Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource converters:TextAlignmentMarginConverter}}" /> 
</Style> 

을 설정합니다.

+0

좋은 방법이지만 변환기는 프로그램의 실행 중에 글꼴 크기가 변경되면 예를 들어 margin 속성이 ' 자동으로 재평가 되려면 명시 적으로 수행해야합니다. 또한 변환기는 여백, 테두리 등과 같은 다른 템플릿 요소를 고려해야하므로 수동 조정 (변환기 매개 변수 일 수도 있음)이 필요합니다. –

+0

보시다시피 저는 전체 컨트롤을 변환기로 전달하므로 매개 변수가 필요 없습니다. 어쨌든, 시간이있을 때 그것을 향상시키기를 바랍니다. 부모의 높이를 기반으로해야하므로 '40'과 같은 정적 값일 필요는 없습니다. – Shimmy

5

정말 여기에 제시하지만 장기적으로 (말장난 의도)에 우리가 사용해야한다고 생각합니까 창조적 인 솔루션과 같은 :

<TextBlock> 
    <Run FontSize="20">What</Run> 
    <Run FontSize="36">ever</Run> 
    <Run FontSize="12" FontWeight="Bold">FontSize</Run> 
</TextBlock> 

실행 요소에서 누락 된 유일한 것입니다 Text 속성의 데이터 바인딩은 조만간 추가 될 수 있습니다.

실행하면 레이블과 텍스트 상자의 맞춤을 수정할 수 없지만 많은 단순한 상황에서는 실행이 아주 잘됩니다.

+0

많은 경우 TextBlock에 적용하지 않고 스타일을 레이블에 쉽게 적용 할 수 있도록 레이블을 선호합니다. 'Name : YOUR NAME HERE'라는 원래의 포스터 예제를 감안할 때 "Name :"텍스트를 유지하기 위해 레이블을 사용하는 것이 더 적절할 것입니다. – jpierson

22

또 다른 아주 간단한 해결책은 :

1)를 사용하여 TextBlock을 대신 레이블로 제어합니다. TextBlock이 Label보다 가벼운 이유 - http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/

2) TextBlock 스타일에 LineHeight 및 LineStackingStrategy = BlockLineHeight를 사용하십시오. 이렇게하면 두 기준을 쉽게 기준에 맞게 조정할 수 있습니다. 이것은해야

<StackPanel Orientation="Horizontal" 
      VerticalAlignment="Center" 
      HorizontalAlignment="Center"> 
    <StackPanel.Resources> 
     <Style TargetType="TextBlock"> 
      <Setter Property="LineHeight" Value="44pt"/> 
      <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/> 
     </Style> 
    </StackPanel.Resources>    
    <TextBlock Text="Name:"/> 
    <TextBlock Text="Itzhak Perlman" FontSize="44"/> 
</StackPanel> 
+0

@Shimmy 이것을 사용해 보셨습니까? 그것은 간단하고 효과적이며 답이되어야합니다. 나를 위해 잘 작동합니다. – ygoe

2
<TextBlock> 
<InlineUIContainer BaselineAlignment="Baseline"><TextBlock>Small</TextBlock></InlineUIContainer> 
<InlineUIContainer BaselineAlignment="Baseline"><TextBlock FontSize="50">Big</TextBlock></InlineUIContainer> 
</TextBlock> 

는 잘 작동합니다. 기준선/바닥/중심점/상단을 사용하여 실험하십시오.

1

XAML 디자이너는 디자인 타임에 기준하여 TextBlock 컨트롤을 정렬 지원 : 이것은 당신의 컨트롤에 고정 된 여백을 지정

enter image description here

. 런타임에 글꼴 크기가 변경되지 않는 한 정렬은 유지됩니다.

+0

예, 작동합니다. 어쩌면이 기능을 질문했을 때 사용할 수 없었을 것입니다 (2010).하지만 Viusal Studio 2015의 WPF 디자이너에서 정렬을 수행 할 수 있음을 확인했습니다 (이 답변의 날짜와 같이 이전 버전에서도 분명히 나타남). 두 조정 된 개체 *에는 텍스트 *가 포함되어야합니다. 레이블 및 텍스트 상자 (일반적으로 비어 있음)는 내부에 일부 텍스트를 임시로 추가합니다. – miroxlav