Stack Overflow на русском Asked by Gnom Skull on December 29, 2020
У меня не получается создать пользовательский элемент который будет авто масштабировать в таблице (grid). Результат которого я хочу добиться это вот:
Т.е чтобы в центре надпись и под ней сама масштабировалась.
Только здесь можно убрать самую верхнюю надпись, и степени окисления которые находятся в правом верхнем углу. Вот мой набросок ( с градиентом и цветом решу в конце, это не сложно).
Но здесь не получается по центру выравнять буквы ( в данном варианте Br). Также здесь может быть минимально одна буква, а максимально 3 буквы. Но так получается что съезжает влево если одна буква или две, если 3 буквы то по размеру часть их скрывалась, я сделал DockPanel и объединил ячейки в центре как на скрине:
Но не получается желаемый результат. Я много разных вариантов перепробовал с border, grid и другими контейнерами. Кто может подсказать как это решить? Я бы просто налепил картинок с уже задаными значениями, но я хочу парсить из базы данных значения и заполнять этими элементами таблицу. Код ниже:
<UserControl x:Class="ChemicalBase.Elements.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ChemicalBase.Elements"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50" MinHeight="50" MinWidth="50" MaxWidth="50" MaxHeight="50">
<Border BorderBrush="White" Background="White">
<Grid Background="#FF58B26D" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9*"/>
<ColumnDefinition Width="9*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Row="1" Grid.ColumnSpan="3" LastChildFill="False">
<TextBlock HorizontalAlignment="Center" DockPanel.Dock="left" TextWrapping="Wrap" Text="Uuh" Width="25" Foreground="White" FontWeight="Bold" Grid.Column="1" RenderTransformOrigin="0.608,0.471" Grid.Row="1" Margin="16,0,6,0"/>
</DockPanel>
<TextBlock TextWrapping="Wrap" Text="111" Grid.Row="2" Grid.Column="0" Foreground="White" FontSize="10"/>
</Grid>
</Border>
</UserControl>
Начнем с того, что в WPF есть такой компонент, как Viewbox
, он автоматически меняет контент, который находится в нем. Viewbox
позволяет настраивать пропорции при помощи свойства Stretch
, допустим нам надо сделать квадрат, который внутри будет иметь некий текст, настраиваем все, делаем как надо, получаем, например такое:
<Border Background="Green" Width="100" Height="100">
<TextBlock Text="Текст"
VerticalAlignment="Center" TextAlignment="Center"
Foreground="White" FontSize="16"
Typography.Capitals="AllSmallCaps"/>
</Border>
Что даст нам предсказуемый результат, где размер будет статичный:
Помещаем это в Viewbox
и задаем Stretch="Uniform"
, разметка превращается в такое:
<Viewbox Stretch="Uniform">
<Border Background="Green" Width="100" Height="100">
<TextBlock Text="Текст"
VerticalAlignment="Center" TextAlignment="Center"
Foreground="White" FontSize="16"
Typography.Capitals="AllSmallCaps"/>
</Border>
</Viewbox>
Результатом уже будет квадрат, который меняет размер и сохраняет все пропорнции:
Имея все это, мы можем сделать уже допустим такое:
<UserControl.Style>
<Style TargetType="UserControl">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Color="#4e9e6d"/>
<GradientStop Color="#0e2806" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#f9fcfd"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="UserControl">
<Viewbox Stretch="Uniform">
<Border Background="{TemplateBinding Background}"
MinWidth="100" MinHeight="100"
Width="100" Height="100"
Padding="3">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="1">
<TextBlock Text="{Binding Text, ElementName=uc, FallbackValue=Text}"
VerticalAlignment="Center" TextAlignment="Center"
Foreground="{TemplateBinding Foreground}"
Typography.Capitals="AllSmallCaps" />
</Viewbox>
<TextBlock Grid.Row="2" Text="{Binding Numb, ElementName=uc, FallbackValue=00}"
Foreground="{TemplateBinding Foreground}"
FontSize="10"/>
</Grid>
</Border>
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Style>
И получим:
Вы спросите: "а зачем тут внутренний текст также обернут в Viewbox
?", а чтобы он органично вписывался в этот квадрат, если там будет больше одной буквы. Небольшая демонстрация:
Как видите, если использовать грамотно позиционирование объектов, а именно использовать разные *Alignment
свойства (допустим центральный текст у меня имеет VerticalAlignment="Center" TextAlignment="Center"
, что устанавливает вертикальный размер элемента строго по контенту, а горизонтальный растягивает на максимально допустимый размер предка, ну и TextAlignment
делает сам текст по середине блока) и Viewbox
, то любой контент без труда можно сделать динамически подстраиваемым.
Correct answer by EvgeniyZ on December 29, 2020
если я правильно понял Вашу проблему, то Вам должна помочь такая разметка:
<WrapPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Stretch" ItemWidth="90">
<Grid Height="auto" Width="auto" Background="#FF58B26D" Margin="5, 5, 0, 5">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
Grid.Row="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="White"
FontSize="35"
TextAlignment="Center">A</TextBlock>
<TextBlock Grid.Column="0"
Grid.Row="2"
Grid.ColumnSpan="3"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Foreground="White"
FontSize="11"
TextAlignment="Center">11111</TextBlock>
</Grid>
</WrapPanel>
Но здесь мы вынуждены контролировать ширину элемента, что бы при изменении текста, сам элемент не расползался и не сужался.
Как Вы можете заметить, я задаю значение для свойства ItemWidth = 90
, что бы контролировать ширину родительского объекта, так же вы можете задать MinWidth
для элемента что бы он не мог стать уже, но мог расшириться, что бы влез весь текст.
Answered by Aleksandr Kurilov on December 29, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP