用户控件内容控件未填写

时间:2016-10-22 09:51:34

标签: xaml user-controls uwp windows-10-universal

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

这是我的结果:

enter image description here

编辑:

不好意思,但是粘贴代码和图片我错了。我更正了: 我的用法如下:

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

这是我的结果: enter image description here

编辑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在设备上运行时放置第二个底部组。

1 个答案:

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