52

コードでマージンを個別に設定できますが、XAMLでどのように設定しますか?たとえば、これを行うにはどうすればよいですか?

擬似コード:

<StackPanel Margin.Top="{Binding TopMargin}">
4

12 に答える 12

57

これはあなたが探しているものではありませんか?

<StackPanel Margin="0,10,0,0" />

最初の値は左マージン、次に上、次に右、最後になりますが下です。

何かにバインドするかどうかはわかりませんが、バインドしない場合は機能します。

于 2009-08-23T08:04:48.020 に答える
45

重要なのは、次のようなコードで設定することを理解することです。

sp2.Margin = new System.Windows.Thickness{ Left = 5 };

と同等です:

sp2.Margin = new System.Windows.Thickness{ Left = 5, Top = 0, Right = 0, Bottom = 0 };

コードまたはXAMLを使用して、インスタンスに1つの値だけを設定することはできません。一部の値を設定しない場合、それらは暗黙的にゼロになります。したがって、これを行うだけで、他の質問で受け入れられたコードサンプルを同等のXAMLに変換できます。Thickness

<StackPanel Margin="{Binding TopMargin, Converter={StaticResource MyConverter}}"/>

ここで、だけを設定し、他のすべての値をゼロのままMyConverterにするaを返します。ThicknessTop

もちろん、これらの個々の値を依存関係プロパティとして公開する独自のコントロールを記述て、コードを少しすっきりさせることができます。

<CustomBorder TopMargin="{Binding TopMargin}">
</CustomBorder>

カスタムコントロールよりも優れたオプションは、添付プロパティを記述し、依存関係プロパティセッターで上記のコードを使用して厚さを変更することです。以下のコードは、マージンのあるすべてのコントロールで使用できます。

public static readonly DependencyProperty TopMarginProperty =
    DependencyProperty.RegisterAttached("TopMargin", typeof(int), typeof(FrameworkElement),
                                        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetTopMargin(FrameworkElement element, int value)
{
    // set top margin in element.Margin
}
public static int GetTopMargin(FrameworkElement element)
{
    // get top margin from element.Margin
}

これをBehaviorと組み合わせると、TopMarginプロパティで通知の変更を取得できます。

于 2009-08-22T18:21:17.150 に答える
22

これは、WPF/XAMLの戒めに属します。

  1. 私はあなたのUIフレームワークであるWPF/XAMLです。最終的には、Windows用のアプリをコーディングするときに私を使用します。
  2. あなたは他のテクノロジーを持ってはいけません-私はクロスプラットフォームにはなりませんが、SilverlightUWP、Hololensはいつか巨大になるからです。「Xamarin.Forms」?聞いたことがない!
  3. WPF / XAMLを使用する場合、必然的に主の名前を繰り返し無駄にする必要があります。
  4. 安息日を覚えておいてください:7日ごと...またはコーディングの数時間または数分私はあなたにStackOverflow2000thingsに行くために休憩をとらせます。
  5. あなたの父と母を称えましょう:Windowsフォーム。
  6. MVVMを採用する場合は、INPCINCCも実装する必要がありますが、喜んでください。あなたには選択肢があります:あなたはそれを使うことができるか、あなたはそれを怒りで使うことができます。
  7. あなたはしてはならない姦淫します他のアプリやフレームワークとの相互運用。
  8. 隣人のUIフレームワークを欲しがってはいけません。
  9. 数行のコードビハインドを記述せずに、アタッチされたプロパティまたはマージンのいずれかのバインディングを使用して要素の位置を動的に設定することはできません。
  10. XAMLに単純なboolVisibilityプロパティを設定することはできません。私はWPF/XAMLです。

あなたの罪は#9にリストされています。

于 2012-07-07T16:00:41.687 に答える
4

バインディングまたは静的リソースから個々のマージン値を簡単に設定できるようにするいくつかの添付プロパティを記述しました。

public class Margin
{
    public static readonly DependencyProperty LeftProperty = DependencyProperty.RegisterAttached(
        "Left",
        typeof(double),
        typeof(Margin),
        new PropertyMetadata(0.0));

    public static void SetLeft(UIElement element, double value)
    {
        var frameworkElement = element as FrameworkElement;
        if (frameworkElement != null)
        {
            Thickness currentMargin = frameworkElement.Margin;

            frameworkElement.Margin = new Thickness(value, currentMargin.Top, currentMargin.Right, currentMargin.Bottom);
        }
    }

    public static double GetLeft(UIElement element)
    {
        return 0;
    }

    public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached(
        "Top",
        typeof(double),
        typeof(Margin),
        new PropertyMetadata(0.0));

    public static void SetTop(UIElement element, double value)
    {
        var frameworkElement = element as FrameworkElement;
        if (frameworkElement != null)
        {
            Thickness currentMargin = frameworkElement.Margin;

            frameworkElement.Margin = new Thickness(currentMargin.Left, value, currentMargin.Right, currentMargin.Bottom);
        }
    }

    public static double GetTop(UIElement element)
    {
        return 0;
    }

    public static readonly DependencyProperty RightProperty = DependencyProperty.RegisterAttached(
        "Right",
        typeof(double),
        typeof(Margin),
        new PropertyMetadata(0.0));

    public static void SetRight(UIElement element, double value)
    {
        var frameworkElement = element as FrameworkElement;
        if (frameworkElement != null)
        {
            Thickness currentMargin = frameworkElement.Margin;

            frameworkElement.Margin = new Thickness(currentMargin.Left, currentMargin.Top, value, currentMargin.Bottom);
        }
    }

    public static double GetRight(UIElement element)
    {
        return 0;
    }

    public static readonly DependencyProperty BottomProperty = DependencyProperty.RegisterAttached(
        "Bottom",
        typeof(double),
        typeof(Margin),
        new PropertyMetadata(0.0));

    public static void SetBottom(UIElement element, double value)
    {
        var frameworkElement = element as FrameworkElement;
        if (frameworkElement != null)
        {
            Thickness currentMargin = frameworkElement.Margin;

            frameworkElement.Margin = new Thickness(currentMargin.Left, currentMargin.Top, currentMargin.Right, value);
        }
    }

    public static double GetBottom(UIElement element)
    {
        return 0;
    }
}

使用法:

<TextBlock Text="Test"
    app:Margin.Top="{Binding MyValue}"
    app:Margin.Right="{StaticResource MyResource}"
    app:Margin.Bottom="20" />

UWPでテストされていますが、これはXAMLベースのフレームワークで機能するはずです。良い点は、マージンの他の値を上書きしないので、それらを組み合わせることもできます。

于 2015-09-05T00:50:52.427 に答える
2

は依存関係オブジェクトではないMarginタイプであるため、バインディングを使用して上マージンだけを定義することはできません。ThicknessただしMultiValueConverter、1つの厚さのオブジェクトを作成するために4つのマージン値をとるを使用することができます

コンバーター:

public class ThicknessMultiConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double left = System.Convert.ToDouble(values[0]);
        double top = System.Convert.ToDouble(values[1]);
        double right = System.Convert.ToDouble(values[2]);
        double bottom = System.Convert.ToDouble(values[3]);
        return new Thickness(left, top, right, bottom);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        Thickness thickness = (Thickness)value;
        return new object[]
        {
            thickness.Left,
            thickness.Top,
            thickness.Right,
            thickness.Bottom
        };
    }

    #endregion
}

XAML:

<StackPanel>
    <StackPanel.Margin>
        <MultiBinding Converter="{StaticResource myThicknessConverter}">
            <Binding Path="LeftMargin"/>
            <Binding Path="TopMargin"/>
            <Binding Path="RightMargin"/>
            <Binding Path="BottomMargin"/>
        </MultiBinding>
    </StackPanel.Margin>
</StackPanel>
于 2009-08-22T17:19:56.667 に答える
1

コンバーターを記述したり、マージン値をハードコーディングしたりせずにこれを行う簡単な方法を次に示します。まず、ウィンドウ(または他のコントロール)リソースで以下を定義します。

<Window.Resources>
    <!-- Define the default amount of space -->
    <system:Double x:Key="Space">10.0</system:Double>

    <!-- Border space around a control -->
    <Thickness
        x:Key="BorderSpace"
        Left="{StaticResource Space}"
        Top="{StaticResource Space}"
        Right="{StaticResource Space}"
        Bottom="{StaticResource Space}"
        />

    <!-- Space between controls that are positioned vertically -->
    <Thickness
        x:Key="TopSpace"
        Top="{StaticResource Space}"
        />
</Window.Resources>

systemとして定義されていることに注意してくださいxmlns:system="clr-namespace:System;assembly=mscorlib"

これで、これらのリソースを次のように使用できます。

<Grid
    Margin="{StaticResource BorderSpace}"
    >
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Button
        Grid.Row="0"
        Content="Button 1"
        />

    <Button
        Grid.Row="1"
        Content="Button 2"
        Margin="{StaticResource TopSpace}"
        />
</Grid>

これで、コントロール間のデフォルトのスペースを変更する場合は、1か所で変更するだけで済みます。

于 2015-07-07T21:24:26.217 に答える
0

コンバーターを使用します。以下のサンプルコードは、バインドしているダブルを厚みに変換します。厚みの「トップ」をバウンドフィールドに設定します。オプションで、ConverterParameterを使用して、左、上、右、または下にバインドしているかどうかを判別できます。

<StackPanel Margin="{Binding TopMargin, Converter={StaticResource MyThicknessConverter}">

public class ThicknessSingleValueConverter : IValueConverter
{
    override Convert(...)
    {
         return new Thickness(0, (double)object, 0, 0);
    }

    //etc...
于 2009-08-22T18:03:14.800 に答える
0

私はあなたがMSDNからのプロパティ構文を使うことができると思いました:

      <object.Margin>
        <Thickness Top="{Binding Top}"/>
      </object.Margin>

あなたがコンバーターを必要としないより

しかし、トップはDependancyPropertyではありません-コンバーターに戻ります

于 2009-10-13T08:42:30.577 に答える
0

これが気の利いた解決策です:

        public class Nifty
    {
        private static double _tiny;
        private static double _small;
        private static double _medium;
        private static double _large;
        private static double _huge;
        private static bool _resourcesLoaded;

        #region Margins

        public static readonly DependencyProperty MarginProperty =
            DependencyProperty.RegisterAttached("Margin", typeof(string), typeof(Nifty),
                new PropertyMetadata(string.Empty,
                    new PropertyChangedCallback(OnMarginChanged)));

        public static Control GetMargin(DependencyObject d)
        {
            return (Control)d.GetValue(MarginProperty);
        }

        public static void SetMargin(DependencyObject d, string value)
        {
            d.SetValue(MarginProperty, value);
        }

        private static void OnMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement ctrl = d as FrameworkElement;
            if (ctrl == null)
                return;

            string Margin = (string)d.GetValue(MarginProperty);

            ctrl.Margin = ConvertToThickness(Margin);
        }

        private static Thickness ConvertToThickness(string Margin)
        {
            var result = new Thickness();

            if (!_resourcesLoaded)
            {
                _tiny = (double)Application.Current.FindResource("TinySpace");
                _small = (double)Application.Current.FindResource("SmallSpace");
                _medium = (double)Application.Current.FindResource("MediumSpace");
                _large = (double)Application.Current.FindResource("LargeSpace");
                _huge = (double)Application.Current.FindResource("HugeSpace");

                _resourcesLoaded = true;
            }

            result.Left = CharToThickness(Margin[0]);
            result.Top = CharToThickness(Margin[1]);
            result.Bottom = CharToThickness(Margin[2]);
            result.Right = CharToThickness(Margin[3]);

            return result;
        }


        private static double CharToThickness(char p)
        {
            switch (p)
            {
                case 't':
                case 'T':
                    return _tiny;
                case 's':
                case 'S':
                    return _small;
                case 'm':
                case 'M':
                    return _medium;
                case 'l':
                case 'L':
                    return _large;
                case 'h':
                case 'H':
                    return _huge;
                default:
                    return 0.0;
            }
        }

        #endregion

    }

このコードを名前空間に追加し、次のサイズを定義する場合:

    <system:Double x:Key="TinySpace">2</system:Double>
<system:Double x:Key="SmallSpace">5</system:Double>
<system:Double x:Key="MediumSpace">10</system:Double>
<system:Double x:Key="LargeSpace">20</system:Double>
<system:Double x:Key="HugeSpace">20</system:Double>

次に、次のように、Tiny、Small、Medium、Large、Hugeのマージンを作成できます。

local:Nifty.Margin="H000"

また

local:Nifty.Margin="_S_S"

コードは、リソースに基づいてマージンを作成します。

于 2011-01-21T16:18:07.177 に答える
0

たぶん私は「パーティーに遅れている」のですが、提供されているソリューションはどれも好きではありませんでした。最も簡単でクリーンなソリューションは、ViewModel(またはバインドしているもの)でThicknessプロパティを定義してから、そのプロパティをバインドすることです。このようなもの:

public class ItemViewModel
{
  public Thickness Margin { get; private set }

  public ItemViewModel(ModelClass model)
  {
    /// You can calculate needed margin here, 
    /// probably depending on some value from the Model
    this.Margin = new Thickness(0,model.TopMargin,0,0);
  }
}

そして、XAMLは単純です。

<StackPanel Margin="{Binding Margin}">
于 2014-07-15T13:12:58.477 に答える
0

Margin(RelativeSource Self)にバインドされたValueConverterを使用し、「top:123; left:456」として指定されたConverterParameterを解析します。

コンバーターは、パラメーターで指定されたマージンのみを上書きします。

public class MarginConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Thickness)) return new Thickness();

        Thickness retMargin = (Thickness) value;
        List<string> singleMargins = (parameter as string)?.Split(';').ToList() ?? new List<string>();

        singleMargins.ForEach(m => {
                                  switch (m.Split(':').ToList()[0].ToLower().Trim()) {
                                      case "left":
                                          retMargin.Left = double.Parse(m.Split(':').ToList()[1].Trim());
                                          break;
                                      case "top":
                                          retMargin.Top = double.Parse(m.Split(':').ToList()[1].Trim());
                                          break;
                                      case "right":
                                          retMargin.Right = double.Parse(m.Split(':').ToList()[1].Trim());
                                          break;
                                      case "bottom":
                                          retMargin.Bottom = double.Parse(m.Split(':').ToList()[1].Trim());
                                          break;
                                  }
                              }
            );
        return retMargin;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

xaml

<TextBlock Margin="{Binding RelativeSource={RelativeSource Self}, 
                    Path=Margin, 
                    Converter={StaticResource MarginConverter}, 
                    ConverterParameter='top:0'}" 
Style="{StaticResource Header}" 
Text="My Header" />

TextBlockは、0で上書きされるMargin-Topを除いて、Styleによって指定されたMarginを使用します。

楽しんでください!

于 2016-08-23T06:36:55.570 に答える
-3

以下のコード例のようなものを指定することでこれを実行できると便利です。

<StackPanel Margin=",10,,">

残念ながら、この機能はWPFにデフォルトで存在しないようであり、開発者が既知のデフォルト値をハードコーディングする必要があり、後でアプリケーションのスキンやテーマを設定するのが難しくなるため、残念です。

この時点で私が考えることができる最善の解決策はコンバーターを使用することですが、これを導入するために生成しなければならない余分なコードの量は理想的ではありません。

于 2010-01-28T14:27:23.370 に答える