web-dev-qa-db-ja.com

StackPanelでアイテム間の間隔を設定する簡単な方法は何ですか?

StackPanel内のアイテム間にデフォルトのスペースを設定する簡単な方法があるので、各アイテムにMarginプロパティを設定する必要はありませんか?

20
Poma

すべてのコントロールが同じである場合は、IanRが提案したとおりに実行し、そのコントロールをキャッチするスタイルを実装します。そうでない場合は、機能しないため、基本クラスにデフォルトのスタイルを作成することはできません。

このような状況に最適な方法は、非常に巧妙なトリックを使用することです-添付プロパティ(別名WPF4の動作)

次のように、プロパティがアタッチされたクラスを作成できます。

public class MarginSetter
{
    public static Thickness GetMargin(DependencyObject obj)
    {
        return (Thickness)obj.GetValue(MarginProperty);
    }

    public static void SetMargin(DependencyObject obj, Thickness value)
    {
        obj.SetValue(MarginProperty, value);
    }

    // Using a DependencyProperty as the backing store for Margin.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MarginProperty =
        DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(MarginSetter), new UIPropertyMetadata(new Thickness(), CreateThicknesForChildren));

    public static void CreateThicknesForChildren(object sender, DependencyPropertyChangedEventArgs e)
    {
        var panel = sender as Panel;

        if (panel == null) return;

        foreach (var child in panel.Children)
        {
            var fe = child as FrameworkElement;

            if (fe == null) continue;

            fe.Margin = MarginSetter.GetMargin(panel);
        }
    }


}

これを使用するには、次のように、この添付プロパティを任意のパネルにアタッチするだけです。

<StackPanel local:MarginSetter.Margin="10">
    <Button Content="hello " />
    <Button Content="hello " />
    <Button Content="hello " />
    <Button Content="hello " />
</StackPanel>

もちろん完全に再利用可能です。

13
Elad Katz

私は透明なセパレーターを使用しています。これはうまく機能します。

<Separator Opacity="0" Height="20"/>

もちろんマージンを使用することもできますが、マージンを変更する場合は、すべての要素を更新する必要があります。

セパレータは、静的リソースでスタイルを設定することもできます。

付属の物件でも可能ですが、やり過ぎだと思います。

44
keyle

受け入れられた答えはもう機能しません。しかし、私はその回答とその回答の作成者(Elad Katz)のブログを使用して、ここで再現する実用的なコード(.Net Coreでテスト済み)を作成しました。

    public static class EstablecedorMargen { 


    public static Thickness GetMargen(DependencyObject objeto) => objeto != null ? (Thickness)objeto.GetValue(PropiedadMargen) : new Thickness();

    public static void SetMargen(DependencyObject objeto, Thickness value) => objeto?.SetValue(PropiedadMargen, value);

    public static readonly DependencyProperty PropiedadMargen 
        = DependencyProperty.RegisterAttached("Margen", typeof(Thickness), typeof(EstablecedorMargen), new UIPropertyMetadata(new Thickness(), Cambió));


    public static void Cambió(object sender, DependencyPropertyChangedEventArgs e) {
        if (!(sender is Panel panel)) return;
        panel.Loaded += new RoutedEventHandler(EstablecerMargenControlesHijos);
    } 


    public static void EstablecerMargenControlesHijos(object sender, RoutedEventArgs e) {

        if (!(sender is Panel panel)) return;
        foreach (var hijo in panel.Children) {
            if (!(hijo is FrameworkElement feHijo)) continue;
            feHijo.Margin = GetMargen(panel);
        }

    } 


} 

次に、以下を使用します。

   <StackPanel local:EstablecedorMargen.Margen="10" >          
            <Button Content="1" />
            <Button Content="2" />
            <Button Content="3" />
    </StackPanel>
0
David