1. 程式人生 > 其它 >WPF 佈局 在有限空間內讓兩個元素儘可能撐開的例子

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

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

我在嘗試寫一個顯示本機 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 資料夾

部落格園部落格只做備份,部落格釋出就不再更新,如果想看最新部落格,請到 https://blog.lindexi.com/


本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含連結:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我[聯絡](mailto:[email protected])。