概要
WPFではStackPanelやGridといったパネルコントロールを使って、望みのレイアウトを表現します。
ほとんどのレイアウトはパネルコントロールの組み合わせで可能ですが、まれに出来ない場合もあります。
そのような場合に添付プロパティを使って、解決する方法を紹介します。
作りたいレイアウト
以下のように長い文字が入るTextBoxと別のコントロール、ここではButtonがいます。
このとき、以下のような動きをしたい、とします。
片方だけならそれぞれGridとStackPanelを使ってできますが、両方を同時に満たすことができません。
- 長い文字が入ってもButtonが画面内に出ていかない、TextBoxの長さを制限したい
- 短い文字の時はTextBoxを縮めてButtonを近くに置きたい
添付プロパティ
MaxWidth
用のLimitMaxWidth
とMaxHeight
用のLimitMaxHeight
の2つのフォーマットを指定できる添付プロパティが定義されています。
classLimitSizeHelper{#regionLimitMaxHeight添付プロパティpublicstaticdoubleGetLimitMaxHeight(DependencyObjectobj)=>(double)obj.GetValue(LimitMaxHeightProperty);publicstaticvoidSetLimitMaxHeight(DependencyObjectobj,doublevalue)=>obj.SetValue(LimitMaxHeightProperty,value);publicstaticreadonlyDependencyPropertyLimitMaxHeightProperty=DependencyProperty.RegisterAttached("LimitMaxHeight",typeof(double),typeof(LimitSizeHelper),newPropertyMetadata(1d,(d,e)=>AddLimitMaxSize(d,e,false)));#endregion#regionLimitMaxWidth添付プロパティpublicstaticdoubleGetLimitMaxWidth(DependencyObjectobj)=>(double)obj.GetValue(LimitMaxWidthProperty);publicstaticvoidSetLimitMaxWidth(DependencyObjectobj,doublevalue)=>obj.SetValue(LimitMaxWidthProperty,value);publicstaticreadonlyDependencyPropertyLimitMaxWidthProperty=DependencyProperty.RegisterAttached("LimitMaxWidth",typeof(double),typeof(LimitSizeHelper),newPropertyMetadata(-1d,(d,e)=>AddLimitMaxSize(d,e,true)));#endregionprivatestaticvoidAddLimitMaxSize(DependencyObjectd,DependencyPropertyChangedEventArgse,boolisWidth){if(disFrameworkElementtargetObj&&targetObj.ParentisPanelpanel&&e.NewValueisdoublenewValue&&newValue>0){panel.SizeChanged+=(o,_)=>Parent_SizeChanged(targetObj,panel,isWidth,newValue);}}privatestaticvoidParent_SizeChanged(FrameworkElementtargetObj,Panelpanel,boolisWidth,doubleratio){varotherSumSize=panel.Children.Cast<FrameworkElement>().Where(x=>x!=targetObj).Sum(x=>isWidth?x.ActualWidth:x.ActualHeight);doublemaxSize=((isWidth?panel.ActualWidth:panel.ActualHeight)-otherSumSize)*ratio;if(isWidth)targetObj.MaxWidth=maxSize;elsetargetObj.MaxHeight=maxSize;}}
使用方法
XAML上で親コントロールに対する比率を指定します。local:LimitSizeHelper.LimitMaxWidth="0.99"
コードビハインドは使用していません。
MainWindow.xaml
<Windowx:Class="LimitSizeControl.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:LimitSizeControl"Width="300"Height="300"><!-- Width制限 --><StackPanelMargin="10"Background="LightSlateGray"Orientation="Horizontal"><TextBoxlocal:LimitSizeHelper.LimitMaxWidth="0.99"Text="LLLLLLLLLLLLLLLOOOOOOOOOOONNNNNNNNNGGGGGG"TextWrapping="Wrap"/><ButtonContent="BUTTON"/></StackPanel><!-- Height制限 --><!--<StackPanel Margin="10" Background="LightSlateGray">
<TextBox
Width="50"
local:LimitSizeHelper.LimitMaxHeight="0.99"
Text="LLLLLLLLLLLLLLLLLLLLLLOOOOOOOOOOOOOOOOOOOOOOOOOOOONNNNNNNNNNNNNNNNNNNNNNNNGHHHHHHHHHHHHHHHHGGGGGGGGG"
TextWrapping="Wrap" />
<Button Content="BUTTON" />
</StackPanel>--></Window>
環境
VisualStudio 2019 Version 16.8.4
.NET 5
C#9
参考
https://qiita.com/YSRKEN/items/686068a359866f21f956
https://www.atmarkit.co.jp/ait/articles/1011/30/news116_2.html