UWP:如何根据网格宽度回流控件

UWP: how to reflow controls based on grid width

我有两个水平放置的按钮。它们在网格内。这个包含两个按钮的网格宽度为 370。当按钮上的文本变大时,它需要的宽度超过 370。所以我想做的是,而不是水平放置,我想在文本开始时动态垂直放置它们裁剪。基本上,我希望基于网格宽度(而不是基于主 window 的宽度)的这两个按钮在该网格内自动回流行为。所以我希望它们适合 370 度宽度,如果不能,我希望它们垂直放置。我怎样才能做到这一点?

我探索了 GridView,但它会在 GridView 附带的框中显示按钮,所以我不想要 GridView 附带的额外 UI,除非我们可以选择隐藏它?

我检查了 AdaptiveTrigger,但它基于 window 的宽度而不是控件的宽度(在本例中为网格)

<Grid
    Grid.Row="2"
    Margin="0,36,0,28"
    Width="370"
    HorizontalAlignment="Left"
    VerticalAlignment="Bottom">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid
        Grid.Column="0"
        CornerRadius="3">
        <Button
            MinWidth="118"
            MinHeight="30"
            HorizontalAlignment="Left"
            HorizontalContentAlignment="Center"
            VerticalContentAlignment="Center"
            AutomationProperties.Name="{x:Bind ViewModel.PrimaryActionAutomationName, Mode=OneWay}"
            BorderThickness="1"
            Click="{x:Bind ViewModel.InvokePrimaryAction}"
            Content="{x:Bind ViewModel.PrimaryAction, Mode=OneWay}"
            CornerRadius="3"
            Style="{StaticResource AccentButtonStyle}" />
    </Grid>
    <Grid
        Grid.Column="1"
        CornerRadius="3"
        Margin="32,0,0,0">
        <HyperlinkButton
            AutomationProperties.Name="{x:Bind ViewModel.SecondaryLinkAutomationName, Mode=OneWay}"
            AutomationProperties.AutomationId="{Binding AutomationId, ConverterParameter=HyperlinkButton, Converter={StaticResource AutomationIdConverter}}"
            Content="{x:Bind ViewModel.SecondaryText, Mode=OneWay}"
            FontSize="14"
            Margin="0,0,0,0"
            Style="{StaticResource HyperlinkButtonStyle}"
            NavigateUri="{x:Bind ViewModel.SecondaryLink, Mode=OneWay}" />
    </Grid>
</Grid>

对于您的场景,我建议您基于 StateTriggerBase Class 自定义一个 StateTrigger 来监控 Grid 的宽度并根据宽度应用视觉状态。

我做了一个简单的例子,你可以参考。

ControlSizeTrigger:

 public class ControlSizeTrigger : StateTriggerBase
{
    //private variables
    private double _minHeight, _minWidth = -1;
    private FrameworkElement _targetElement;
    private double _currentHeight, _currentWidth;
    //public properties to set from XAML
    public double MinHeight
    {
        get
        {
            return _minHeight;
        }
        set
        {
            _minHeight = value;
        }
    }
    public double MinWidth
    {
        get
        {
            return _minWidth;
        }
        set
        {
            _minWidth = value;
        }
    }
    public FrameworkElement TargetElement
    {
        get
        {
            return _targetElement;
        }
        set
        {
            if (_targetElement != null)
            {
                _targetElement.SizeChanged -= _targetElement_SizeChanged;
            }
            _targetElement = value;
            _targetElement.SizeChanged += _targetElement_SizeChanged;
        }
    }
    //Handle event to get current values
    private void _targetElement_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        _currentHeight = e.NewSize.Height;
        _currentWidth = e.NewSize.Width;
        UpdateTrigger();
    }
    //Logic to evaluate and apply trigger value
    private void UpdateTrigger()
    {
        //if target is set and either minHeight or minWidth is set, proceed
        if (_targetElement != null && (_minWidth > 0 || _minHeight > 0))
        {
            //if both minHeight and minWidth are set, then both conditions must be satisfied
            if (_minHeight > 0 && _minWidth > 0)
            {
                SetActive((_currentHeight >= _minHeight) && (_currentWidth >= _minWidth));
            }
            //if only one of them is set, then only that condition needs to be satisfied
            else if (_minHeight > 0)
            {
                SetActive(_currentHeight >= _minHeight);

            }
            else
            {
                SetActive(_currentWidth >= _minWidth);
                bool bbb = _currentWidth >= _minWidth;
                Debug.WriteLine("Widthtrigger :" + bbb);
            }
        }
        else
        {
            SetActive(false);
        }
    }

}

MainPage.xaml:

 <Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ControlSizeStates">
            <VisualState x:Name="SizeChange">
                <VisualState.StateTriggers>
                    <local:ControlSizeTrigger MinWidth="800" TargetElement="{x:Bind Path=MyStackPanel}" />
                    <!--<AdaptiveTrigger MinWindowHeight="500" />-->
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="MyStackPanel.Background" Value="Red" />
                    <Setter Target="MyStackPanel.Orientation" Value="Horizontal" />
                    <Setter Target="MyButton.Foreground" Value="Black" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    
    <StackPanel x:Name="MyStackPanel" Width="100" Height="200" Background="AliceBlue" Orientation="Vertical">
        
       
        <Button x:Name="MyButton" Foreground="Red" Content="Click" Click="Button_Click"/>
        <Button x:Name="MyButton2" Foreground="Red" Content="Click" />
    </StackPanel>
   
</Grid>

MainPage.cs:

  public MainPage()
    {
        this.InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MyStackPanel.Width = 1100;
    }