我有一个多行单选按钮,我希望子弹在内容的左侧(默认情况下)与单选按钮控件的顶部对齐。在XAML中最简单的方法是什么?
答案 0 :(得分:17)
注意:请务必查看Rachel's answer - 她将这一阶段进一步纳入通用模板
首先,不要在VerticalAlignment
或VerticalContentAlignment
(甚至ControlTemplate
)上浪费时间。他们不会做你想做或想做的事。
如MSDN所述BulletDecorator
(这是CheckBox和RadioButton用于呈现收音机/检查按钮的控件)将自动设置图标的位置。您无法对此进行额外控制:
当子项时,子弹始终与第一行文本对齐 object是一个文本对象。如果Child对象不是文本对象,则 Bullet对齐Child对象的中心。
除非您更改控制模板(不必要),否则只有在内容为文本时才能将收音机/支票图标置于顶部。
因此,如果您执行此类操作,则效果不佳,因为无论您尝试设置多少VerticalAlignment
个属性,都无法移动图标。
<RadioButton>
<StackPanel>
<TextBlock Text="First line"/>
<TextBlock Text="Something else"/>
</StackPanel>
</RadioButton>
但幸运的是,您可以使用TextBlock
在InlineUIContainer
中放置您想要的任何内容。第一行中的文本(或内容)将自动指示图标的位置。如果您想要第一行下面不是文字的内容,请使用<Linebreak/>
,然后使用<InlineUIContainer/>
这是一个超大TextBox
的示例,可以更清楚地显示正在发生的事情。
<RadioButton>
<TextBlock VerticalAlignment="Top" TextWrapping="Wrap">
<TextBlock Text="Products with <" VerticalAlignment="Center" Margin="0,0,5,0"/>
<InlineUIContainer BaselineAlignment="Center">
<TextBox FontSize="30" Width="25" Text="10" Margin="0,0,5,0"/>
</InlineUIContainer>
<TextBlock VerticalAlignment="Center" Margin="0,0,5,0">
<Run Text="days" FontWeight="Bold"/>
<Run Text="inventory" />
</TextBlock>
<LineBreak/>
<InlineUIContainer>
<StackPanel>
<CheckBox Content="Include unsold products" />
<CheckBox Content="Include something else" />
</StackPanel>
</InlineUIContainer>
</TextBlock>
</RadioButton>
答案 1 :(得分:14)
我已经构建了一个基于Simon Weaver's answer的相对通用的模板,可以在大多数情况下使用,而无需记住始终自定义RadioButton.Content
。
<ControlTemplate x:Key="MultiLineRadioButtonTemplate" TargetType="{x:Type RadioButton}">
<RadioButton IsChecked="{TemplateBinding IsChecked}">
<TextBlock>
<LineBreak />
<InlineUIContainer>
<ContentPresenter Margin="0,-21,0,8"
Content="{TemplateBinding ContentPresenter.Content}"
ContentTemplate="{TemplateBinding ContentPresenter.ContentTemplate}"/>
</InlineUIContainer>
</TextBlock>
</RadioButton>
</ControlTemplate>
解释模板的工作原理:
TextBlock
是存在的,因为默认情况下,如果内容是Text对象,则RadioButton项目符号与文本的第一行对齐(Label
将不起作用)
LineBreak
是将内容包装到新行,因此创建了第一行
InlineUIContainer
是我们可以将非文字内容放入TextBlock
ContentPresenter
用于保存实际内容,并且上边距为负,以移除LineBreak
对象留下的空间。
以下是一些示例内容:
<StackPanel>
<RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}">
<StackPanel>
<Label Content="Option 1" />
<StackPanel>
<CheckBox Content="Some setting" />
<CheckBox Content="Some other setting" />
</StackPanel>
</StackPanel>
</RadioButton>
<RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}">
<StackPanel>
<Label Content="Option 2" />
<DataGrid AutoGenerateColumns="False" Height="100">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" />
<DataGridTextColumn Header="Date" />
<DataGridTextColumn Header="Total" />
<DataGridTextColumn Header="Count" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</RadioButton>
<RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}">
<StackPanel>
<Label Content="Option 3" />
<TextBlock TextWrapping="WrapWithOverflow" Margin="2">
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</TextBlock>
</StackPanel>
</RadioButton>
</StackPanel>
它看起来如何:
我唯一不满意的是ContentPresenter
被硬编码的负上边距,因为如果您更改字体大小,则必须手动调整该边距。
为Margin
属性构建一个转换器,计算换行符的高度({TemplateBinding FontSize}
?),甚至扩展版本的RadioButton控件可能不会那么难默认情况下会出现这种情况,但是现在基于我的应用程序的默认字体大小,我可以使用硬编码-21。
另外,如果要继承原始TemplateBindings
中的其他属性,可能需要向模板中的RadioButton
添加一些RadioButton
,例如边距,填充,对齐,我只是为了保持简单而绑定IsChecked
。
答案 2 :(得分:2)
覆盖RadioButton的Control.Template。以下是MSDN Radio Button Control Template Example
中的示例如果您不想覆盖单选按钮的Control.Template,则可以将内容设为Wrapped TextBlock。看这个样本
<RadioButton Name="radioButton1">
<TextBlock TextWrapping="Wrap">Here is some multiline text that does some wrapping</TextBlock>
</RadioButton>