【问题标题】:Best way to implement margin between WPF/SL grid columns/rows在 WPF/SL 网格列/行之间实现边距的最佳方法
【发布时间】:2010-10-15 08:52:19
【问题描述】:

在 WPF 或 Silverlight 网格中的列或行之间添加边距的最佳方法是什么?

  1. 将固定宽度/高度的列/行添加到网格中
  2. 为网格子控件添加边距
  3. 还有别的吗?

提前致谢

【问题讨论】:

    标签: wpf silverlight grid


    【解决方案1】:

    这实际上取决于您的设计,并且取决于您自己的口味。最重要的是要保持一致。

    我认为在大多数情况下放置一个固定宽度的“间隔”列或行是完全可以接受的 - 这样您就不必担心以后的维护(无论是您还是其他人)。

    需要注意的是设置两次(即边距和固定宽度列)。如果您使用所有相同类型的控件,这不是什么大问题,但如果您使用不同类型的控件,这些控件应用了包括边距和/或填充在内的样式,则问题可能会变得有点难看。

    【讨论】:

      【解决方案2】:

      如果您不介意从 Grid 派生自己的控件并改用它,那么您可以很容易地做到这一点。由于这似乎是一个好主意,我很快就编写了这个(大部分未经测试且非常丑陋!)代码:

      /// <summary>
      /// Enhanced Grid that can automatically apply a padding to all its children.
      /// </summary>
      public class PaddedGrid : Grid
      {
      
          /// <summary>
          /// Gets or sets a padding value to apply as the margin to all children.
          /// If left to default (null or 'zero' Thickness) the margins of the children are not modified.
          /// </summary>
          public Thickness? Padding
          {
              get { return (Thickness?)GetValue(PaddingProperty); }
              set { SetValue(PaddingProperty, value); }
          }
      
          public static readonly DependencyProperty PaddingProperty =
              DependencyProperty.Register("Padding", typeof(Thickness?), typeof(PaddedGrid), new PropertyMetadata(PaddingChanged));
      
          private bool HasPadding()
          {
              return Padding.HasValue && Padding.Value != default(Thickness);
          }
      
          private static void PaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
              var g = d as PaddedGrid;
              if (g != null)
              {
                  if (!g.HasPadding()) return;
                  for (int i = 0; i < g.VisualChildrenCount; i++)
                  {
                      var v = g.GetVisualChild(i);
                      var c = v as FrameworkElement;
                      if (c == null || c is GridSplitter) continue;
                      c.Margin = (Thickness)e.NewValue;
                  }
              }
          }
      
          protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
          {
              base.OnVisualChildrenChanged(visualAdded, visualRemoved);
              if (!HasPadding()) return;
              if (visualAdded != null)
              {
                  var fe = visualAdded as FrameworkElement;
                  if (fe != null) fe.Margin = this.Padding.Value;
              }
          }
      }
      

      【讨论】:

      • 感谢您的回答,问题是我不希望边距是自动的,而是要控制它应该应用于哪些列和行。
      • 好吧,您可以随时根据自己的喜好扩展它。例如,您可以接受行和列的单独值作为字符串,并在字符串中放置表示边距的逗号分隔值。但是,由于网格没有将行和列作为“子项”,因此您需要确定子视觉对象位于哪一行和哪一列上(使用 Grid.Row 和 Grid.Column 附加属性)。天空是极限,但当然,创建自己的迷你网格对齐框架没有多大意义,除非你真的要在很多的地方使用它。
      • 我最同意你最后的说法:“当然,除非你真的要在很多地方使用它,否则创建你自己的迷你网格对齐框架没有多大意义。”这个解决方案虽然有它的位置,但比大多数解决方案需要的复杂得多,这可能使其更难以维护(尤其是当您开始添加可解析参数等时)