StackPanel の子要素の間隔を空けるにはどうすればよいですか?
-
06-09-2019 - |
質問
StackPanel を指定すると、次のようになります。
<StackPanel>
<TextBox Height="30">Apple</TextBox>
<TextBox Height="80">Banana</TextBox>
<TextBox Height="120">Cherry</TextBox>
</StackPanel>
子要素自体のサイズが異なる場合でも、子要素間に同じサイズの隙間ができるように、子要素の間隔を空ける最善の方法は何でしょうか?個々の子のプロパティを設定せずにそれを行うことはできますか?
解決
マージンやパディングを使用して、容器内の範囲に適用される
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
</StackPanel.Resources>
<TextBox Text="Apple"/>
<TextBox Text="Banana"/>
<TextBox Text="Cherry"/>
</StackPanel>
EDIT:あなたは二つの容器の間のマージンを再利用したい場合は、あなたが、外側のスコープ内のリソースにf.eをマージン値を変換することができます。
<Window.Resources>
<Thickness x:Key="tbMargin">0,10,0,0</Thickness>
</Window.Resources>
、次に内側範囲でこの値を参照する
<StackPanel.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="{StaticResource tbMargin}"/>
</Style>
</StackPanel.Resources>
他のヒント
別の優れたアプローチをここで見ることができます。http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easyest-way-to-set-spacing-between-items-in-stackpanel.aspx
アタッチされた動作を作成する方法を示しており、次のような構文が機能します。
<StackPanel local:MarginSetter.Margin="5">
<TextBox Text="hello" />
<Button Content="hello" />
<Button Content="hello" />
</StackPanel>
これは、たとえ同じタイプでなくても、パネルの複数の子に Margin を設定する最も簡単かつ迅速な方法です。(つまり、ボタン、テキストボックス、コンボボックスなど)
上達しました エラッド・カッツの答え.
- LastItemMargin プロパティを MarginSetter に追加して、最後の項目を特別に処理します。
- 垂直リストと水平リストの項目間にスペースを追加し、リストの末尾の末尾のマージンを削除する、Vertical プロパティと horizontal プロパティを持つ Spacing 添付プロパティを追加します。
例:
<StackPanel Orientation="Horizontal" foo:Spacing.Horizontal="5">
<Button>Button 1</Button>
<Button>Button 2</Button>
</StackPanel>
<StackPanel Orientation="Vertical" foo:Spacing.Vertical="5">
<Button>Button 1</Button>
<Button>Button 2</Button>
</StackPanel>
<!-- Same as vertical example above -->
<StackPanel Orientation="Vertical" foo:MarginSetter.Margin="0 0 0 5" foo:MarginSetter.LastItemMargin="0">
<Button>Button 1</Button>
<Button>Button 2</Button>
</StackPanel>
あなたが本当にやりたい事は、すべての子要素をラップです。この場合、あなたはアイテムコントロールを使用する必要がありますし、あなたがスタイルに望むすべてのプロパティのための百万を持つことになります恐ろしい添付プロパティに頼るません。
<ItemsControl>
<!-- target the wrapper parent of the child with a style -->
<ItemsControl.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Margin" Value="0 0 5 0"></Setter>
</Style>
</ItemsControl.ItemContainerStyle>
<!-- use a stack panel as the main container -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- put in your children -->
<ItemsControl.Items>
<Label>Auto Zoom Reset?</Label>
<CheckBox x:Name="AutoResetZoom"/>
<Button x:Name="ProceedButton" Click="ProceedButton_OnClick">Next</Button>
<ComboBox SelectedItem="{Binding LogLevel }" ItemsSource="{Binding LogLevels}" />
</ItemsControl.Items>
</ItemsControl>
Sergey の回答に +1。それをすべての StackPanel に適用したい場合は、次のようにすることができます。
<Style TargetType="{x:Type StackPanel}">
<Style.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="{StaticResource tbMargin}"/>
</Style>
</Style.Resources>
</Style>
ただし、次のことに注意してください。 App.xaml (または Application.Resources にマージされる別の辞書) でこのようなスタイルを定義すると、 できる コントロールのデフォルトのスタイルをオーバーライドします。スタックパネルのようなほとんど見た目のないコントロールの場合は問題ありませんが、テキストボックスなどではつまずく可能性があります。 この問題, 、幸いなことに、これにはいくつかの回避策があります。
Sergey の提案に従って、Thickness オブジェクトだけでなく、Style 全体 (Margin を含むさまざまなプロパティ セッターを使用) を定義して再利用できます。
<Style x:Key="MyStyle" TargetType="SomeItemType">
<Setter Property="Margin" Value="0,5,0,5" />
...
</Style>
...
<StackPanel>
<StackPanel.Resources>
<Style TargetType="SomeItemType" BasedOn="{StaticResource MyStyle}" />
</StackPanel.Resources>
...
</StackPanel>
ここでのトリックは、暗黙的なスタイルにスタイル継承を使用し、外部 (おそらく外部 XAML ファイルからマージされた) リソース ディクショナリのスタイルから継承していることに注意してください。
サイドノート:
最初に、私は単純に暗黙的なスタイルを使用して、コントロールの Style プロパティを外部の Style リソース (たとえば、キー「MyStyle」で定義) に設定しようとしました。
<StackPanel>
<StackPanel.Resources>
<Style TargetType="SomeItemType">
<Setter Property="Style" Value={StaticResource MyStyle}" />
</Style>
</StackPanel.Resources>
</StackPanel>
これにより、Visual Studio 2010 が CATASTROPHIC FAILURE エラー (HRESULT:0x8000FFFF (E_UNEXPECTED))、で説明されているように https://connect.microsoft.com/VisualStudio/フィードバック/詳細/753211/xaml-editor-window-fails-with-catastrophic-failure-when-a-style-tries-to-set-style-property#
Grid.ColumnSpacing 、 Grid.RowSpacing 、 StackPanel.Spacing 全てがここに要求されているものより良いacomplishにできるようになります、UWPプレビューになりました。
これらのプロパティは、現在、Windows 10秋クリエイター更新インサイダーSDKでのみ使用可能ですが、最終ビットにそれを作る必要があります!
UniformGridは、Silverlightで使用できない場合があり、誰かがWPFからそれを移植しました。 http://www.jeff.wilcox.name/2009/01/uniform -grid / の
私のアプローチは、のStackPanelを継承します。
使用方法:
<Controls:ItemSpacer Grid.Row="2" Orientation="Horizontal" Height="30" CellPadding="15,0">
<Label>Test 1</Label>
<Label>Test 2</Label>
<Label>Test 3</Label>
</Controls:ItemSpacer>
すべてのことが必要なの次に短いクラスがあります:
using System.Windows;
using System.Windows.Controls;
using System;
namespace Controls
{
public class ItemSpacer : StackPanel
{
public static DependencyProperty CellPaddingProperty = DependencyProperty.Register("CellPadding", typeof(Thickness), typeof(ItemSpacer), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCellPaddingChanged));
public Thickness CellPadding
{
get
{
return (Thickness)GetValue(CellPaddingProperty);
}
set
{
SetValue(CellPaddingProperty, value);
}
}
private static void OnCellPaddingChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
((ItemSpacer)Object).SetPadding();
}
private void SetPadding()
{
foreach (UIElement Element in Children)
{
(Element as FrameworkElement).Margin = this.CellPadding;
}
}
public ItemSpacer()
{
this.LayoutUpdated += PART_Host_LayoutUpdated;
}
private void PART_Host_LayoutUpdated(object sender, System.EventArgs e)
{
this.SetPadding();
}
}
}
時にはあなたは、デフォルトの
よりも小さい項目間のスペースを作るためのマージンは、パディングを設定する必要はありません