Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9513

添付プロパティを使ってGridやStackPanelだけで表現できないレイアウトを実現する

$
0
0

概要

WPFではStackPanelやGridといったパネルコントロールを使って、望みのレイアウトを表現します。
ほとんどのレイアウトはパネルコントロールの組み合わせで可能ですが、まれに出来ない場合もあります。
そのような場合に添付プロパティを使って、解決する方法を紹介します。

作りたいレイアウト

以下のように長い文字が入るTextBoxと別のコントロール、ここではButtonがいます。

このとき、以下のような動きをしたい、とします。
片方だけならそれぞれGridとStackPanelを使ってできますが、両方を同時に満たすことができません。

  • 長い文字が入ってもButtonが画面内に出ていかない、TextBoxの長さを制限したい
  • 短い文字の時はTextBoxを縮めてButtonを近くに置きたい

添付プロパティ

MaxWidth用のLimitMaxWidthMaxHeight用の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


Viewing all articles
Browse latest Browse all 9513

Trending Articles