[UWP]大家好,我正在努力使用usercontrol,我在文本框内部发布不同的StackPanel,创建了自己的字段容器(groupbox)。
但是当我插入StackPanel时,您无法有效地填充空白空间。我尝试在各种选项中设置strecth,但没有。
这是我的usercontrol的代码:
<UserControl Name="groupBoxUC"
x:Class="AgendaUWP.Common.CustomControls.GroupBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AgendaUWP.Common.CustomControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:interop="using:Windows.UI.Xaml.Interop"
mc:Ignorable="d"
d:DesignHeight="200"
d:DesignWidth="300">
<StackPanel x:Name="myStackPanel" BorderThickness="1" BorderBrush="Gray" Orientation="Vertical">
<StackPanel Margin="10 0 0 0" HorizontalAlignment="Left" >
<Border Background="{StaticResource secondaryColor}" Height="5" Width="{Binding ActualWidth, ElementName=HeaderText}"/>
<TextBlock x:Name="HeaderText" FontSize="18" FontWeight="ExtraLight" Text="{x:Bind Header,Mode=TwoWay}"/>
</StackPanel>
<ContentControl Padding="10 20 10 20" Content="{Binding InnerContent,ElementName=groupBoxUC}" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" />
</StackPanel>
My Code-Bheind UserControl:
[ContentProperty(Name = "InnerContent")]
public sealed partial class GroupBox : UserControl
{
internal static readonly DependencyProperty InnerContentProperty =
DependencyProperty.Register("InnerContent", typeof(object), typeof(GroupBox), new PropertyMetadata(null));
internal static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(GroupBox), new PropertyMetadata(null));
public GroupBox()
{
this.InitializeComponent();
}
public object InnerContent
{
get { return (object)GetValue(InnerContentProperty); }
set { SetValue(InnerContentProperty, value); }
}
public string Header
{
get { return (string) GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
}
这就是我使用它的方式:
<CustomControls:GroupBox x:Name="grpCoordinate" Header="Coordinate" Margin="30,40,30,0" >
<StackPanel HorizontalAlignment="Left">
<TextBox Header="Longitudine:" Text="{x:Bind ViewModel.Cliente.Longitudine, Mode=TwoWay}" HorizontalAlignment="Stretch" />
<TextBox Header="Latitudine:" Text="{x:Bind ViewModel.Cliente.Latitudine, Mode=TwoWay}" HorizontalAlignment="Stretch" />
</StackPanel>
</CustomControls:GroupBox>
这是我的结果:
编辑:
不好意思,但是粘贴代码和图片我错了。我更正了: 我的用法如下:
<CustomControls:GroupBox x:Name="grpDatiAnagrafici" Header="Dati Anagrafici" VerticalAlignment="Top" Margin="30,0,30,0" Grid.Column="0" Grid.Row="0" >
<StackPanel x:Name="stkDatiAnagrafici" Orientation="Horizontal">
<StackPanel Padding="0 0 20 0">
<TextBox Header="Codice:" Text="{x:Bind ViewModel.Cliente.Codice, Mode=TwoWay}" IsReadOnly="True" IsEnabled="False"/>
<TextBox Header="Ragione Sociale:" Text="{x:Bind ViewModel.Cliente.RagioneSociale, Mode=TwoWay}" />
<TextBox Header="Nome:" Text="{x:Bind ViewModel.Cliente.Nome, Mode=TwoWay}" />
<TextBox Header="Cognome:" Text="{x:Bind ViewModel.Cliente.Cognome, Mode=TwoWay}" />
</StackPanel>
<StackPanel>
<TextBox Header="Indirizzo:" Text="{x:Bind ViewModel.Cliente.Indirizzo, Mode=TwoWay}" />
<TextBox Header="Comune:" Text="{x:Bind ViewModel.Cliente.Comune, Mode=TwoWay}" />
<TextBox Header="Cap:" Text="{x:Bind ViewModel.Cliente.Cap, Mode=TwoWay}" />
<TextBox Header="Provincia:" Text="{x:Bind ViewModel.Cliente.Provincia, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
</CustomControls:GroupBox>
编辑2:
感谢澄清,但有一种方法可以保留StackPanel? 我会解释因为我必须管理VisualStateManager:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="stkDatiAnagrafici.Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="stkDatiAnagrafici.Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
因为如果我使用网格,我还必须指定Grid.Row在设备上运行时放置第二个底部组。
答案 0 :(得分:2)
从包含HorizontalAlignment="Left"
内两个文本框的StackPanel
中移除InnterContent
。
<CustomControls:GroupBox x:Name="grpCoordinate" Header="Coordinate" Margin="30,40,30,0">
<StackPanel> <!-- Removed HorizontalAlignment="Left" from here -->
<TextBox Header="Longitudine:" Text="{x:Bind ViewModel.Cliente.Longitudine, Mode=TwoWay}" HorizontalAlignment="Stretch" />
<TextBox Header="Latitudine:" Text="{x:Bind ViewModel.Cliente.Latitudine, Mode=TwoWay}" HorizontalAlignment="Stretch" />
</StackPanel>
</CustomControls:GroupBox>
此外,这不是必要的,但我将ContentControl
更改为ContentPresenter
。您可以避免使用ElementName绑定,而只需直接使用x:Bind:
<ContentPresenter Padding="10 20 10 20" Content="{x:Bind InnerContent}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
修改强>
水平StackPanel
不能分配每个子元素的可用空间,它只是尊重每个孩子的DesiredSize
。您需要改为使用Grid
。
<Grid x:Name="stkDatiAnagrafici">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Padding="0 0 20 0">
<TextBox Header="Codice:" Text="{x:Bind ViewModel.Cliente.Codice, Mode=TwoWay}" IsReadOnly="True" IsEnabled="False"/>
<TextBox Header="Ragione Sociale:" Text="{x:Bind ViewModel.Cliente.RagioneSociale, Mode=TwoWay}" />
<TextBox Header="Nome:" Text="{x:Bind ViewModel.Cliente.Nome, Mode=TwoWay}" />
<TextBox Header="Cognome:" Text="{x:Bind ViewModel.Cliente.Cognome, Mode=TwoWay}" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBox Header="Indirizzo:" Text="{x:Bind ViewModel.Cliente.Indirizzo, Mode=TwoWay}" />
<TextBox Header="Comune:" Text="{x:Bind ViewModel.Cliente.Comune, Mode=TwoWay}" />
<TextBox Header="Cap:" Text="{x:Bind ViewModel.Cliente.Cap, Mode=TwoWay}" />
<TextBox Header="Provincia:" Text="{x:Bind ViewModel.Cliente.Provincia, Mode=TwoWay}" />
</StackPanel>
</Grid>
编辑2
您仍然可以使用Grid
,只需在视觉状态中设置正确的属性即可为其提供正确的外观。你无法使用StackPanel
,因为它不会分配其子女的宽度。
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="stack1.Padding" Value="0"/>
<Setter Target="stack2.Padding" Value="0"/>
<Setter Target="stack2.(Grid.Column)" Value="0"/>
<Setter Target="stack2.(Grid.Row)" Value="1"/>
<Setter Target="stkDatiAnagrafici.ColumnDefinitions[1].Width" Value="0"/>
<Setter Target="stkDatiAnagrafici.RowDefinitions[1].Height" Value="*"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<CustomControls:GroupBox x:Name="grpDatiAnagrafici" Header="Dati Anagrafici" VerticalAlignment="Top" Margin="30,0,30,0" Grid.Column="0" Grid.Row="0" >
<Grid x:Name="stkDatiAnagrafici">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<StackPanel x:Name="stack1" Grid.Column="0" Padding="0 0 10 0">
<TextBox Header="Codice:" IsReadOnly="True" IsEnabled="False"/>
<TextBox Header="Ragione Sociale:"/>
<TextBox Header="Nome:"/>
<TextBox Header="Cognome:"/>
</StackPanel>
<StackPanel x:Name="stack2" Grid.Column="1" Padding="10 0 0 0">
<TextBox Header="Indirizzo:"/>
<TextBox Header="Comune:"/>
<TextBox Header="Cap:"/>
<TextBox Header="Provincia:"/>
</StackPanel>
</Grid>
</CustomControls:GroupBox>
EDIT 2B
如果您想要更通用的解决方案(超过2列),那么您始终可以编写自己的自定义StackPanel
来均匀分配空间:
class FilledStackPanel : StackPanel
{
protected override Size MeasureOverride(Size availableSize)
{
var childSize = Orientation == Orientation.Horizontal ?
new Size(availableSize.Width / Children.Count, availableSize.Height) :
new Size(availableSize.Width, availableSize.Height / Children.Count);
double alongAxis = 0;
double crossAxis = 0;
foreach (var child in Children)
{
child.Measure(childSize);
if (Orientation == Orientation.Horizontal)
{
alongAxis += child.DesiredSize.Width;
crossAxis = Math.Max(crossAxis, child.DesiredSize.Height);
}
else
{
alongAxis += child.DesiredSize.Height;
crossAxis = Math.Max(crossAxis, child.DesiredSize.Width);
}
}
return Orientation == Orientation.Horizontal ?
new Size(alongAxis, crossAxis) :
new Size(crossAxis, alongAxis);
}
protected override Size ArrangeOverride(Size finalSize)
{
var childSize = Orientation == Orientation.Horizontal ?
new Size(finalSize.Width / Children.Count, finalSize.Height) :
new Size(finalSize.Width, finalSize.Height / Children.Count);
double alongAxis = 0;
foreach (var child in Children)
{
if (Orientation == Orientation.Horizontal)
{
child.Arrange(new Rect(alongAxis, 0, childSize.Width, childSize.Height));
alongAxis += childSize.Width;
}
else
{
child.Arrange(new Rect(0, alongAxis, childSize.Width, childSize.Height));
alongAxis += childSize.Height;
}
}
return finalSize;
}
}
现在您不需要使用Grid
,可以使用FilledStackPanel
代替StackPanel
。