WPF 布局 在有限空間內讓兩個元素盡可能撐開的例子


我在嘗試寫一個顯示本機 WIFI 熱點的賬號和密碼的控件,要求此控件在有限的空間內顯示。但是盡可能顯示出熱點的賬號和密碼。而熱點的賬號和密碼是用戶配置的,也許長度很長。我的需求是在假如賬號的長度較短的時候,將剩余的空間盡可能給到密碼的顯示。反過來,在密碼長度比較短的時候,將剩余的空間給到賬號的顯示。如果兩者的長度都比較長,那么同時限制兩者的最大尺寸

有以下的不同的情況的需求

  • 賬號和密碼的長度都較短,可以完全顯示

  • 賬號較長,密碼較短,但合起來的長度小於最大尺寸。期望能完全顯示出來

  • 賬號超長,可以限制賬號顯示的最大長度

  • 賬號超長,密碼較長,將會因為限制最大尺寸,而裁剪賬號和密碼顯示內容

  • 賬號較短,密碼較長,可以讓密碼占用更多的空間

  • 如果賬號還沒達到限制的最大寬度,密碼超長,那么裁剪密碼內容

也就是說需要相當於在 Grid 里面造兩個可以撐開的 * 長度的,但是限制最大尺寸的布局。不過本文將用另一個方法,采用 StackPanel 加上轉換器來實現

先給 StackPanel 設置最大的寬度尺寸,接着設置 StackPanel 采用水平布局的方式。當然了本文的方法對於垂直布局也是生效的,只需要大家將對應的水平布局修改為垂直布局即可

   <StackPanel x:Name="OuterStackPanel" MaxWidth="300" Orientation="Horizontal">
   </StackPanel>

在 StackPanel 里面放入必要的控件,其中對於賬號的內容顯示,只需要設置 MaxWidth 最大寬度即可。因為總的寬度計算是依靠 StackPanel 進行限制,而賬號內容顯示的控件的尺寸,是依靠后面的密碼顯示控件控制的

    <StackPanel x:Name="OuterStackPanel" MaxWidth="300" Orientation="Horizontal">
            <TextBlock x:Name="SSIDTextBlock" d:Text="熱點:" Text="熱點:" FontSize="14" />
            <TextBlock x:Name="SSIDContentTextBlock" d:Text="SSID" Text="{Binding ElementName=NameTextBox,Path=Text}" FontSize="14" MaxWidth="150" TextTrimming="CharacterEllipsis" />
            <TextBlock x:Name="SpaceTextBlock" Text="   " FontSize="14" />
   </StackPanel>

通過 SpaceTextBlock 控件,用來分割距離

接着就是加上,密碼顯示模塊。在密碼顯示里面,傳入 OuterStackPanel 里面,除了 SSIDContentTextBlock 綁定賬號內容的空間外的其他控件的尺寸,用來計算剩余給 賬號內容顯示控件 和 密碼內容顯示控件 的總空間。再通過設置自身的最大空間占用值,即可在 賬號內容顯示控件 沒有占用較多空間時,盡可能撐開 密碼內容顯示控件 大小

            <TextBlock x:Name="PasswordTextBlock" d:Text="密碼:" Text="密碼:" FontSize="14" />
            <TextBlock x:Name="PasswordContentTextBlock" Grid.Column="4"  d:Text="Password" Text="{Binding ElementName=KeyTextBox,Path=Text}" FontSize="14" TextTrimming="CharacterEllipsis">
                <TextBlock.MaxWidth>
                    <MultiBinding Converter="{StaticResource MirrorPopupContentPasswordMaxWidthConverter}">
                        <Binding ElementName="OuterStackPanel" Path="MaxWidth"/>
                        <Binding ElementName="SSIDTextBlock" Path="ActualWidth"/>
                        <Binding ElementName="SSIDContentTextBlock" Path="ActualWidth"/>
                        <Binding ElementName="SpaceTextBlock" Path="ActualWidth"/>
                        <Binding ElementName="PasswordTextBlock" Path="ActualWidth"/>
                    </MultiBinding>
                </TextBlock.MaxWidth>
            </TextBlock>

以上的 MirrorPopupContentPasswordMaxWidthConverter 的代碼定義如下


    public class MirrorPopupContentPasswordMaxWidthConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values[0] is double total)
            {
            	// 一下的 Skip 傳入 1 表示的是跳過第 1 個控件的寬度計算
            	// 第 1 個控件是賬號內容顯示控件
                foreach (var val in values.OfType<double>().Skip(1))
                {
                    total -= val;
                }

                return total > 0 ? total : 0;
            }
            return DependencyProperty.UnsetValue;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

通過此方式即可實現在有限的空間內,讓兩個元素盡可能撐開

特別感謝 lsj 提供的方法

本文以上的代碼放在githubgitee 歡迎訪問

可以通過如下方式獲取本文的源代碼,先創建一個空文件夾,接着使用命令行 cd 命令進入此空文件夾,在命令行里面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 87fb070b57a1d4364f7c460d7f33c20545974dd0

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

獲取代碼之后,進入 NawhejefurWheekaijerehu 文件夾


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM