WPF: Đặt Chiều rộng (và Chiều cao) làm Giá trị phần trăm


149

Nói rằng tôi muốn TextBlocknó có giá trị Widthtương đương với Công cụ chứa cha mẹ Width(nghĩa là kéo dài từ bên này sang bên kia) hoặc tỷ lệ phần trăm của Container mẹ Width, làm cách nào tôi có thể thực hiện việc này XAMLmà không chỉ định giá trị tuyệt đối?

Tôi muốn làm điều này để nếu Container chứa sau này được mở rộng ( Widthtăng ' ), các phần tử con của nó cũng sẽ được mở rộng tự động. (về cơ bản, như trong HTML và CSS)


Có một cái nhìn vào câu trả lời này .
Jesper Fyhr Knudsen

Sử dụng câu trả lời của cwap và đưa tb vào cài đặt lưới để căn chỉnh của nó kéo dài.
Shimmy Weitzhandler

Câu trả lời:


90

Cách để kéo dài nó đến cùng kích thước với vùng chứa cha là sử dụng thuộc tính:

 <Textbox HorizontalAlignment="Stretch" ...

Điều đó sẽ làm cho phần tử Textbox kéo dài theo chiều ngang và lấp đầy tất cả không gian cha theo chiều ngang (thực ra nó phụ thuộc vào bảng cha bạn đang sử dụng nhưng nên hoạt động trong hầu hết các trường hợp).

Tỷ lệ phần trăm chỉ có thể được sử dụng với các giá trị ô lưới, vì vậy một tùy chọn khác là tạo lưới và đặt hộp văn bản của bạn vào một trong các ô có tỷ lệ phần trăm phù hợp.


221

Bạn có thể đặt các hộp văn bản bên trong một lưới để thực hiện các giá trị phần trăm trên các hàng hoặc cột của lưới và để các hộp văn bản tự động điền vào các ô cha của chúng (theo mặc định chúng sẽ như vậy). Thí dụ:

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

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

Điều này sẽ làm cho # 1 2/5 chiều rộng và # 2 3/5.


7
Tôi đã thử điều đó, nhưng tôi nhận được lỗi này: chuỗi '2 *' không thể được chuyển đổi thành Độ dài. '
Andreas Grech

6
Trên thực tế, * (Asterisk) là ngôi sao nhỏ;) etymonline.com/index.php?term=asterisk
Pratik Deoghare

73
Mẹ tôi nói tôi là một ngôi sao
Denys Wessels

7
Điều này không hoạt động, ngay cả khi TextBox nằm trong Lưới. Chiều rộng có thể được đặt thành Double, Double Qualified (Giá trị kép theo sau là px, in, cm hoặc pt) hoặc Auto. Xem msdn.microsoft.com/en-GB/l Library / Mạnh
Darren

2
Vâng .. Đây thực sự là một câu trả lời rất kém, nhưng dựa trên tất cả các upvote, tôi cho rằng nó đã giúp được ai đó (đã lâu rồi), đó là lý do tại sao tôi chưa xóa nó.
cwap

58

Thông thường, bạn sẽ sử dụng điều khiển bố cục tích hợp phù hợp với kịch bản của mình (ví dụ: sử dụng lưới làm cha mẹ nếu bạn muốn chia tỷ lệ so với cha mẹ). Nếu bạn muốn làm điều đó với một phần tử cha tùy ý, bạn có thể tạo một ValueConverter làm điều đó, nhưng có lẽ nó sẽ không hoàn toàn sạch như bạn muốn. Tuy nhiên, nếu bạn thực sự cần nó, bạn có thể làm một cái gì đó như thế này:

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

Có thể được sử dụng như thế này, để có được một hộp văn bản con 10% chiều rộng của khung vẽ chính của nó:

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

Điều này thực sự thú vị, làm thế nào tôi có thể làm điều đó trong mã (đặt chiều rộng của hộp văn bản)?
Jeremy

9
Bạn nên xem xét thêm CultureInfo.InvariantCulturevào chuyển đổi kép vì parameterđược coi là stringvà trong các nền văn hóa khác nhau, decimal separatornó sẽ không hoạt động như mong đợi.
Căn hộ Eric

33

Đối với bất kỳ ai đang gặp lỗi như: chuỗi '2 *' không thể được chuyển đổi thành Độ dài.

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

Tại sao không <RowDefinition Height="auto" />?
Ben

2
"tự động" chỉ chiếm nhiều dung lượng như nhu cầu điều khiển
Yama

Cảm ơn bạn rất nhiều, đây nên là câu trả lời hàng đầu.
Mafii

Đây chắc chắn là câu trả lời tốt nhất.
Knut Valen

7

IValueConverter có thể được sử dụng. Lớp chuyển đổi nhận thừa kế từ IValueConverter lấy một số tham số như value(phần trăm) và parameter(chiều rộng của cha mẹ) và trả về giá trị chiều rộng mong muốn. Trong tệp XAML, chiều rộng của thành phần được đặt với giá trị mong muốn:

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>

4

Tôi biết đó không phải là Xaml nhưng tôi đã làm điều tương tự với sự kiện SizeChanged của hộp văn bản:

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

Hộp văn bản dường như có kích thước 80% so với cha mẹ của nó (lề bên phải là 20%) và kéo dài khi cần.


4

Tôi sử dụng hai phương pháp để định cỡ tương đối. Tôi có một lớp được gọi Relativevới ba tài sản gắn liền To, WidthPercentHeightPercentđó là hữu ích nếu tôi muốn có một yếu tố để trở thành một kích thước tương đối của một bất cứ nơi nào yếu tố trong cây thị giác và cảm thấy ít hacky so với phương pháp chuyển đổi - mặc dù sử dụng nào phù hợp với bạn, rằng bạn hạnh phúc với.

Cách tiếp cận khác là khá khôn ngoan hơn. Thêm một ViewBoxnơi bạn muốn kích thước tương đối bên trong, sau đó bên trong đó, thêm Gridchiều rộng 100. Sau đó, nếu bạn thêm một TextBlockchiều rộng 10 bên trong đó, rõ ràng là 10% của 100.

Ý ViewBoxchí sẽ chia tỷ lệ Gridtheo bất kỳ không gian nào đã được cung cấp, vì vậy nếu đó là thứ duy nhất trên trang, thì nó Gridsẽ được thu nhỏ toàn bộ chiều rộng và hiệu quả, TextBlocktỷ lệ của bạn được chia tỷ lệ thành 10% của trang.

Nếu bạn không đặt chiều cao Gridthì nó sẽ co lại để phù hợp với nội dung của nó, vì vậy tất cả sẽ có kích thước tương đối. Bạn sẽ phải đảm bảo rằng nội dung không quá cao, tức là bắt đầu thay đổi tỷ lệ khung hình của không gian được cung cấp cho không gian ViewBoxkhác, nó cũng sẽ bắt đầu nhân rộng chiều cao. Bạn có lẽ có thể làm việc xung quanh điều này với một Stretchsố UniformToFill.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.