Pertanyaan Batasi bagian bawah teks dalam kontrol


Cuplikan berikut:

<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>

Berikan yang berikut:
alt text

Apakah ada cara yang dapat saya atur dalam gaya Label sehingga bidang teks mereka harus disejajarkan?
Saya memiliki pertanyaan yang sama dengan TextBlocks juga.

CATATAN: karena saya telah berjuang dengan masalah ini untuk sementara waktu, tolong posting hanya jawaban tertentu yang Anda tahu pekerjaan itu.
Saya sudah mencoba: VerticalAlignment, VerticalContentAlignment, Padding, Margin. Apakah ada hal lain yang tidak saya ketahui?

Saya telah membaca ini posting, tetapi tidak berbicara tentang skenario ukuran font yang berbeda.

MEMPERBARUI: Masalahnya adalah, bahwa bahkan Padding diatur ke 0 masih ada ruang tak tentu di sekitar font, di dalam area ContentPresenter. ruang ini bervariasi pada ukuran font. Jika saya bisa mengendalikan ruang ini, saya akan berada dalam situasi yang lebih baik.

Terima kasih


16
2018-01-10 03:09


asal


Jawaban:


Tidak ada solusi XAML saja, Anda harus menggunakan kode di belakang. Juga, bahkan dengan kode di belakang, tidak ada solusi umum untuk ini, karena bagaimana jika teks Anda multi-baris? Baseline mana yang harus digunakan dalam kasus itu? Atau bagaimana jika ada beberapa elemen teks di template Anda? Seperti header dan konten, atau lebih, yang mana dasar itu?

Singkatnya, taruhan terbaik Anda adalah menyelaraskan teks secara manual menggunakan margin atas / bawah.

Jika Anda bersedia membuat asumsi bahwa Anda memiliki elemen teks tunggal, Anda dapat mengetahui jarak piksel baseline dari bagian atas elemen oleh instantiate FormattedText objek dengan semua properti yang sama dari elemen teks yang ada. Itu FormattedText objek memiliki double  Baseline properti yang menyimpan nilai itu. Perhatikan bahwa Anda masih harus memasukkan margin secara manual, karena elemen tersebut mungkin tidak persis sama dengan bagian atas atau bawah wadahnya.

Lihat posting forum MSDN ini: Baseline Textbox

Inilah metode yang saya tulis yang mengekstraksi nilai itu. Ini menggunakan refleksi untuk mendapatkan properti yang relevan karena mereka tidak umum untuk kelas dasar tunggal (mereka didefinisikan secara terpisah pada Control, TextBlock, Page, TextElement dan mungkin lainnya).

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, sebagai tanggapan atas komentar Anda, saya tidak percaya Anda benar-benar telah mencoba solusi ini, karena berhasil. Inilah contohnya:

Example Baseline Alignment

Inilah 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>

Dan inilah kode di balik yang mencapai ini

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);

6
2018-01-10 13:43



Solusi lain yang cukup sederhana:

1) Gunakan kontrol TextBlock sebagai ganti Label. Alasannya adalah bahwa TextBlock lebih ringan daripada Label - lihat http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/

2) Gunakan LineHeight dan LineStackingStrategy = BlockLineHeight untuk gaya TextBlock Anda. Ini akan menyelaraskan keduanya di garis dasar mereka dengan mudah.

<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>

23
2017-11-29 16:40



Saya sangat suka solusi kreatif yang disajikan di sini tetapi saya berpikir bahwa dalam jangka panjang (pun intended) kita harus menggunakan ini:

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

Satu-satunya hal yang hilang dari elemen Run adalah penyatuan data dari properti Text tapi itu mungkin ditambahkan cepat atau lambat.

A Run tidak akan memperbaiki penyelarasan label dan kotak teks mereka, tetapi untuk banyak situasi sederhana, Run akan berjalan dengan baik.


5
2018-01-20 14:59



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

Ini seharusnya bekerja dengan baik. Bereksperimen dengan Baseline / Bottom / Center / Top.


2
2018-03-28 08:10



Desainer XAML mendukung penyelarasan TextBlock kontrol berdasarkan baseline pada waktu desain:

enter image description here

Ini menetapkan margin tetap untuk kontrol Anda. Selama ukuran font tidak berubah pada waktu berjalan, penyelarasan akan dipertahankan.


1
2017-11-20 15:35



Saya benar-benar menemukan jawaban sederhana berdasarkan Aviad's.

Saya membuat konverter yang berisi fungsi Aviad yang menerima elemen itu sendiri dan mengembalikan Ketebalan terhitung.

Kemudian saya mengaturnya

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

Kerugiannya adalah bahwa ini jelas menempati properti Margin asli, karena TextBlock tidak memiliki template sehingga kami tidak dapat mengaturnya melalui TemplateBinding.


0
2018-01-11 00:56