¿Cómo establecer un margen superior solo en XAML?


Puedo establecer márgenes individualmente en code pero cómo lo hago en XAML, por ejemplo, cómo hago esto:

PSEUDO-CÓDIGO:

<StackPanel Margin.Top="{Binding TopMargin}">
Author: Community, 2009-08-22

12 answers

La clave es darse cuenta de que configurarlo en código como este:

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

Es equivalente a:

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

Usted no puede establecer un solo valor en una instancia Thickness a través de ya sea código o XAML. Si no establece algunos de los valores, serán implícitamente cero. Por lo tanto, puede hacer esto para convertir el ejemplo de código aceptado en su otra pregunta a un equivalente XAML:

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

Donde MyConverter solo devuelve un Thickness que establece solo el Top y deja todo otros valores como cero.

Por supuesto, usted podría escribir su propio control que hace exponer estos valores individuales como propiedades de dependencia para hacer su código un poco más limpio:

<CustomBorder TopMargin="{Binding TopMargin}">
</CustomBorder>
 33
Author: Kent Boogaart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-27 14:58:18

No es esto lo que estás buscando?

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

El primer valor es Margen izquierdo, luego Superior, luego Derecho y por último, pero no menos importante, Inferior.

No estoy seguro de si quieres vincularlo a algo, pero si no, eso funcionará.

 53
Author: Carlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-23 08:04:48

Esto pertenece a las enmiendas del WPF:

  1. Soy WPF y me usarás cuando codifiques para aplicaciones de Windows, eventualmente.
  2. No uses otras tecnologías - no seré multiplataforma pero lo intentaré con SL.
  3. Si tiene la intención de usarme, asegúrese de saber lo que está haciendo.
  4. Cada 7 días u horas o minutos de codificación te haré tomar un descanso para ir a TAN.
  5. Respeta los formularios de windows.
  6. MVVM - > INPC, INCC - > puede usarlo o puede usarlo con la ira - su elección!
  7. No interop otras aplicaciones.
  8. También pagarás por la mezcla.
  9. Usted no será capaz de establecer una posición de un elemento dinámicamente utilizando el enlace de una propiedad adjunta o margen sin escribir pocas líneas de código detrás.

  10. No compare esta tecnología con otras.

Su problema aparece en el #9.

 20
Author: G.Y,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 17:56:09

No se puede definir solo el margen superior con un enlace, porque Margin es de tipo Thickness que no es un objeto de dependencia. Sin embargo, podría usar un MultiValueConverter que tomaría 4 valores de margen para hacer 1 objetos de espesor

Convertidor:

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>
 1
Author: Thomas Levesque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-22 17:19:56

Use un convertidor, el código de ejemplo a continuación convertirá el doble al que está enlazando a un grosor. Establecerá la "Parte superior" del grosor en el campo encuadernado. Opcionalmente, puede usar un parámetro de conversión para determinar si está enlazando a la izquierda, arriba, derecha o abajo.

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

.

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

    //etc...
 0
Author: NotDan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-22 18:03:14

Aquí hay una solución ingeniosa:

        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

    }

Si agrega este código a su espacio de nombres y define los siguientes tamaños:

    <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>

Luego puede crear márgenes Pequeños, Pequeños, Medianos, Grandes y enormes como este:

local:Nifty.Margin="H000"

O

local:Nifty.Margin="_S_S"

El código creará márgenes basados en sus recursos.

 0
Author: sambeau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-21 16:18:07

Aquí hay una manera simple de hacer esto sin escribir convertidores o valores de margen de codificación rígida. Primero, defina lo siguiente en su Ventana (u otro control) recursos:

<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>

Tenga en cuenta que system se define como xmlns:system="clr-namespace:System;assembly=mscorlib".

Ahora puede usar estos recursos de la siguiente manera:

<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>

Ahora, si desea cambiar el espacio predeterminado entre los controles, solo necesita cambiarlo en un solo lugar.

 0
Author: redcurry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-07 21:24:26

Acaba de escribir algunas propiedades adjuntas que deberían facilitar el establecimiento de un valor de margen individual desde un recurso vinculante o estático:

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;
    }
}

Uso:

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

Probado en UWP pero esto debería funcionar para cualquier framework basado en XAML. Lo bueno es que no anularán los otros valores en el Margen, por lo que también puede combinarlos.

 0
Author: RandomEngy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-05 00:50:52

Utilizo un ValueConverter enlazado a Margin (RelativeSource Self) y analizo el parámetro Converter, dado como "top:123;left:456".

El Convertidor solo sobrescribe los márgenes dados por el Parámetro.

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 usaría el Margen dado por el Estilo excepto el Margen-Top, que se sobrescribirá con 0.

Diviértete con él!

 0
Author: WPFGermany,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-23 06:42:37

Tal vez llegue "tarde a la fiesta", pero no me gustó ninguna de las soluciones proporcionadas, y me parece que la solución más simple y limpia es definir la propiedad Thickness en ViewModel (o cualquier cosa que esté enlazando) y luego Enlazar esa propiedad. Algo como esto:

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);
  }
}

Y luego XAML es simple:

<StackPanel Margin="{Binding Margin}">
 0
Author: Antonio Bakula,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-11 16:57:17

Pensé que podría usar la sintaxis de propiedades, de MSDN :

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

Entonces no necesitará ningún convertidor

Pero la parte superior no es DependancyProperty-volver al convertidor

 -1
Author: Amittai Shapira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-15 06:35:36

Lo que sería bueno es poder hacer esto especificando algo como el ejemplo de código a continuación.

<StackPanel Margin=",10,,">

Desafortunadamente, esta capacidad no parece existir por defecto en WPF y es una pena porque requiere que los desarrolladores codifiquen los valores predeterminados conocidos de una manera que más tarde hace que sea más difícil de skin o tema de una aplicación.

La mejor solución que se me ocurre en este momento es usar un convertidor, pero la cantidad de código adicional que tiene que producir para introducir esto no es ideal.

 -3
Author: jpierson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-28 14:35:30