WPF: Mengatur Lebar (dan Tinggi) sebagai Nilai Persentase

149

Katakanlah saya ingin TextBlockmemiliki yang Widthsetara dengan Parent-nya Width(yaitu, membentang dari sisi ke sisi) atau persentase dari itu Parent Container Width, bagaimana saya bisa mencapai ini XAMLtanpa menentukan nilai absolut?

Saya ingin melakukan ini sehingga jika wadah Induk kemudian diperluas (' Widthmeningkat),' Elemen Anak-nya juga akan diperluas secara otomatis. (pada dasarnya, seperti dalam HTML dan CSS)

Andreas Grech
sumber
Lihatlah jawaban ini .
Jesper Fyhr Knudsen
Gunakan jawaban cwap dan sertakan tb dalam pengaturan kisi untuk menyelaraskannya.
Shimmy Weitzhandler

Jawaban:

90

Cara untuk merentangkannya ke ukuran yang sama dengan wadah induk adalah dengan menggunakan atribut:

 <Textbox HorizontalAlignment="Stretch" ...

Itu akan membuat elemen Textbox membentang secara horizontal dan mengisi semua ruang induk secara horizontal (sebenarnya itu tergantung pada panel induk yang Anda gunakan tetapi harus bekerja untuk sebagian besar kasus).

Persentase hanya dapat digunakan dengan nilai sel kisi sehingga opsi lain adalah membuat kisi dan meletakkan kotak teks Anda di salah satu sel dengan persentase yang sesuai.

gcores
sumber
221

Anda bisa meletakkan kotak teks di dalam kisi untuk melakukan nilai persentase pada baris atau kolom kisi dan membiarkan kotak teks mengisi otomatis ke sel induknya (seperti yang akan secara default). Contoh:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>

    <TextBox Grid.Column="0" />
    <TextBox Grid.Column="1" />
</Grid>

Ini akan membuat # 1 2/5 dari lebarnya, dan # 2 3/5.

cwap
sumber
7
Saya sudah mencobanya, tetapi saya mendapatkan kesalahan ini: string '2 *' tidak dapat dikonversi ke Panjang. '
Andreas Grech
6
Sebenarnya, * (Asterisk) adalah bintang kecil;) etymonline.com/index.php?term=asterisk
Pratik Deoghare
73
Ibuku bilang aku seorang bintang
Denys Wessels
7
Ini tidak berfungsi, bahkan jika TextBox berada dalam Grid. Lebar dapat diatur ke Double, Qualified Double (Nilai ganda diikuti oleh px, in, cm atau pt) atau Otomatis. Lihat msdn.microsoft.com/en-GB/library/…
Darren
2
Ya .. Ini sebenarnya jawaban yang sangat buruk, tetapi berdasarkan semua upvotes, saya kira itu membantu seseorang (sudah lama sekali), itulah sebabnya saya belum menghapusnya.
cwap
58

Biasanya, Anda akan menggunakan kontrol tata letak bawaan yang sesuai untuk skenario Anda (mis. Gunakan kisi sebagai orangtua jika Anda ingin menskalakan relatif terhadap induk). Jika Anda ingin melakukannya dengan elemen induk sewenang-wenang, Anda bisa membuat ValueConverter melakukannya, tetapi mungkin tidak akan sebersih yang Anda inginkan. Namun, jika Anda benar-benar membutuhkannya, Anda dapat melakukan sesuatu seperti ini:

public class PercentageConverter : IValueConverter
{
    public object Convert(object value, 
        Type targetType, 
        object parameter, 
        System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) * 
               System.Convert.ToDouble(parameter);
    }

    public object ConvertBack(object value, 
        Type targetType, 
        object parameter, 
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Yang dapat digunakan seperti ini, untuk mendapatkan kotak teks anak 10% dari lebar kanvas induknya:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <local:PercentageConverter x:Key="PercentageConverter"/>
    </Window.Resources>
    <Canvas x:Name="canvas">
        <TextBlock Text="Hello"
                   Background="Red" 
                   Width="{Binding 
                       Converter={StaticResource PercentageConverter}, 
                       ElementName=canvas, 
                       Path=ActualWidth, 
                       ConverterParameter=0.1}"/>
    </Canvas>
</Window>
kvb
sumber
Ini sangat keren, bagaimana saya bisa melakukannya dalam kode (atur lebar kotak teks)?
Jeremy
9
Anda harus mempertimbangkan CultureInfo.InvariantCultureuntuk menambahkan konversi ganda karena parameterdianggap sebagai stringdan dalam budaya yang berbeda decimal separatoritu tidak akan berfungsi seperti yang diharapkan.
Flat Eric
33

Bagi siapa saja yang mendapatkan kesalahan seperti: string '2 *' tidak dapat dikonversi ke Panjang.

<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" /><!--This will make any control in this column of grid take 2/5 of total width-->
        <ColumnDefinition Width="3*" /><!--This will make any control in this column of grid take 3/5 of total width-->
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition MinHeight="30" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="0" Grid.Row="0">Your text block a:</TextBlock>
    <TextBlock Grid.Column="1" Grid.Row="0">Your text block b:</TextBlock>
</Grid>
Zain Ali
sumber
Mengapa tidak <RowDefinition Height="auto" />?
Ben
2
"otomatis" hanya membutuhkan ruang sebanyak yang dibutuhkan kontrol
Yama
Terima kasih banyak, ini harus menjadi jawaban teratas.
Mafii
Ini jelas merupakan jawaban terbaik.
Knut Valen
7

Implementasi IValueConverter dapat digunakan. Kelas konverter yang mengambil warisan dari IValueConverter mengambil beberapa parameter seperti value(persentase) dan parameter(lebar induk) dan mengembalikan nilai lebar yang diinginkan. Dalam file XAML, lebar komponen diatur dengan yang diinginkan dengan nilai:

public class SizePercentageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter == null)
            return 0.7 * value.ToDouble();

        string[] split = parameter.ToString().Split('.');
        double parameterDouble = split[0].ToDouble() + split[1].ToDouble() / (Math.Pow(10, split[1].Length));
        return value.ToDouble() * parameterDouble;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Don't need to implement this
        return null;
    }
}

XAML:

<UserControl.Resources>
    <m:SizePercentageConverter x:Key="PercentageConverter" />
</UserControl.Resources>

<ScrollViewer VerticalScrollBarVisibility="Auto"
          HorizontalScrollBarVisibility="Disabled"
          Width="{Binding Converter={StaticResource PercentageConverter}, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualWidth}"
          Height="{Binding Converter={StaticResource PercentageConverter}, ConverterParameter=0.6, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}">
....
</ScrollViewer>
Adem Catamak
sumber
4

Saya tahu ini bukan Xaml tapi saya melakukan hal yang sama dengan event SizeChanged dari textbox:

private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
   TextBlock textBlock = sender as TextBlock;
   FrameworkElement element = textBlock.Parent as FrameworkElement;
   textBlock.Margin = new Thickness(0, 0, (element.ActualWidth / 100) * 20, 0);
}

Kotak teks tampaknya berukuran 80% dari induknya (margin sisi kanan adalah 20%) dan membentang bila diperlukan.

Crippeoblade
sumber
4

Saya menggunakan dua metode untuk ukuran relatif. Saya memiliki kelas yang disebut Relativedengan tiga properti terlampir To, WidthPercentdanHeightPercent yang berguna jika saya ingin sebuah elemen menjadi ukuran relatif dari suatu elemen di mana saja di pohon visual dan terasa kurang hacky daripada pendekatan konverter - meskipun menggunakan apa yang bekerja untuk Anda, bahwa Anda senang dengan.

Pendekatan lain agak lebih licik. Tambahkan di ViewBoxmana Anda ingin ukuran relatif di dalam, lalu di dalam itu, tambahkan Gridpada lebar 100. Kemudian jika Anda menambahkan TextBlockdengan lebar 10 di dalamnya, itu jelas 10% dari 100.

The ViewBoxakan skala yang Gridsesuai dengan apa pun ruang yang telah diberikan, jadi jika yang satu-satunya hal pada halaman, maka Gridakan ditingkatkan keluar lebar penuh dan efektif, AndaTextBlock adalah skala untuk 10% dari halaman.

Jika Anda tidak mengatur ketinggian pada Gridmaka itu akan menyusut agar sesuai dengan isinya, jadi semuanya akan berukuran relatif. Anda harus memastikan bahwa kontennya tidak terlalu tinggi, yaitu mulai mengubah rasio aspek dari ruang yang diberikan kepada yang ViewBoxlain itu akan mulai mengukur ketinggian juga. Anda mungkin dapat bekerja di sekitar ini dengan Stretchdari UniformToFill.

Luke Puplett
sumber