【问题标题】:MaxWidth of 'Auto'?“自动”的最大宽度?
【发布时间】:2017-01-27 16:46:52
【问题描述】:

我正在尝试创建一个处理不同尺寸屏幕的网格。我的代码目前如下所示:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" ... />
    <TextBlock Grid.Column="1" ... />
</Grid>

这不能正常工作,因为当我处于全屏模式时,我在第一列的末尾有一个巨大的空白区域,并且我希望每列中的文本相邻。但是,当我缩小/调整屏幕大小时,它确实会正确缩小第一列。

我也尝试过使用这样的代码:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" ... />
    <TextBlock Grid.Column="1" ... />
</Grid>

当应用程序全屏时,此代码看起来很完美,但当我缩小/调整屏幕大小时,第一列不会缩小以适应。它使我的网格保持相同的大小,从而将我的文本从较小的屏幕上推开。

如何将宽度限制为“自动”的任何大小,并且仍然像“*”一样调整大小?

【问题讨论】:

    标签: uwp uwp-xaml


    【解决方案1】:

    如何将宽度限制为“自动”的任何大小,并且仍然像“*”一样调整大小?

    根据Define page layouts with XAMLAuto 表示该列将调整大小以适应其内容,* 表示在计算 Auto 列之后,该列获得剩余宽度的一部分。

    ColumnDefinition 中的Width 不能设置为Auto*。但是由于您的问题是当将Auto 设置为ColumnDefinition 时,它会将您的文本推离较小的屏幕,因此我们可以在这里使用AdaptiveTrigger。我们可以将Width默认设置为*,这样可以保证resize不会截断文本。当窗口调整到不会导致文本被截断的更大尺寸时,AdaptiveTrigger 可以帮助将Width 属性从* 更改为Auto。例如:

    <Grid
       Background="Azure"
       BorderBrush="Pink"
       BorderThickness="2">
       <Grid.ColumnDefinitions>
           <ColumnDefinition x:Name="col1" Width="*" />
           <ColumnDefinition Width="Auto" />
       </Grid.ColumnDefinitions>
       <TextBlock        
           Grid.Column="0"        
           Foreground="Blue"
           Text="layouttest1layouttest1layouttest1layou"
           TextWrapping="Wrap"  />
       <TextBlock     
           Grid.Column="1"           
           Foreground="Red"
           Text="layouttest2layouttest2layouttest2layouttest2layout"
           TextWrapping="Wrap" />
       <VisualStateManager.VisualStateGroups>
           <VisualStateGroup>
               <VisualState>
                   <VisualState.StateTriggers>
                       <AdaptiveTrigger MinWindowWidth="600" />
                   </VisualState.StateTriggers>
                   <VisualState.Setters>
                       <Setter Target="col1.Width" Value="Auto" />
                   </VisualState.Setters>
               </VisualState>
           </VisualStateGroup>
       </VisualStateManager.VisualStateGroups>
    </Grid>
    

    MinWindowWidth 的值取决于TextBlock 的总Width。更多详情请参考official sample

    如果TextBlock中的Width是动态的,则更新代码如下。

    XAML 代码

    <Grid
        Background="Azure"
        BorderBrush="Pink"
        BorderThickness="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="col1" Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <TextBlock        
            Grid.Column="0"  
            x:Name="txt1"
            Foreground="Blue"
            Text="layouttest1layouttest1layouttest1layou"
            TextWrapping="Wrap"  />
        <TextBlock     
            Grid.Column="1"           
            Foreground="Red"
            x:Name="txt2"
            Text="layouttest2layouttest2layouttest2layouttest2layout"
            TextWrapping="Wrap" />     
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger x:Name="adptivetrigger"   />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="col1.Width" Value="Auto" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
    

    后面的代码

     private void Page_Loaded(object sender, RoutedEventArgs e)
     {
         var testwidth = txt1.ActualWidth + txt2.ActualWidth;
         adptivetrigger.MinWindowWidth = testwidth;          
     }
    

    【讨论】:

    • 接近了,但是你从哪里得到 MinWindowWidth="600" 的值?由于每个 TextBlock 的长度可以变化,我永远不会知道 * 和 Auto 之间的确切转折点。当它设置为自动时,我不需要'600'作为第一列的宽度吗?我不能将该值设置为第一列的 MaxWidth 并获得相同的结果吗?
    • @TS,MinWindowWidth 是两个TextBlock 的汇总ActualWidth。如果实际宽度是动态的,您可以在代码后面计算它并将其设置为触发器。我更新了您可以参考的回复中的代码。顺便说一句,如果我的回复对您有帮助,请您标记为已接受。
    • 我得到了我想要的……虽然我最终放弃了 VisualStateManager。基本上我把你的代码隐藏起来,而不是用它来设置'adptivetrigger.MinWindowWidth',而是用它来设置'col1.MaxWidth'。它仍然需要调整以使其与位于其内部的 ItemsControl 一起工作(可能使 MaxWidth 成为绑定),但这个概念是可靠的。谢谢!
    【解决方案2】:

    你可以试试这个

    <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" ... HorizontalAlignment="Stretch"/>
    <TextBlock Grid.Column="1" ... HorizontalAlignment="Stretch"/>
    

    在这里,我刚刚添加了 Horizo​​ntalAlignment="Stretch" 属性,它将对齐列内的文本块拉伸

    【讨论】:

    • 不好。如果第一列只有一点文本,那么每个 TextBlock 之间仍然存在间隙。如果有很多文本,那么第一列将不会扩展以适应文本,即使第二列末尾有一堆空白。
    • 您想根据第一列包含的文本调整第一列的宽度吗?那么如果第二列有一些文本,那么第二列应该发生什么?
    • 我想要的是让两列都像它们的宽度一样自动但是当屏幕缩小或它们的组合文本太大时,只有第一列会缩小或有截断文本。第一列的 TextBlock 具有 TextTrimming="CharacterEllipsis" 以使其适合该列(如果它太小)。这是因为第一列包含项目的描述,我可以排除其中的一部分,第二列包含项目的当前状态,不应隐藏或切断。我还需要消除这些 TextBlocks 之间的任何差距。
    猜你喜欢
    • 1970-01-01
    • 2015-06-30
    • 2015-11-01
    • 2018-07-09
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2012-11-13
    相关资源
    最近更新 更多