在DataGrid中控制水平网格线可见性

时间:2009-08-26 15:05:39

标签: silverlight-3.0

我有一个样式要求,我的数据网格每隔3行显示水平网格线......

这样的事情:

-----------------------------------
one  | two | three  | four   |
five | six | seven  | eight  |
nine | ten | eleven | twelve |
-----------------------------------
aaa  | bbb | ccc    | ddd    |
eee  | fff | ggg    | hhh    |
iii  | jjj | kkk    | lll    |
-----------------------------------
mmm  | nnn | ooo    | ppp    |

等。

有谁知道实现这一目标的简单方法?我正在考虑更新行样式以包含边框,并将每个(x mod n)次的底部边框厚度设置为1,但这似乎不对。

必须有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

所以,在黑客攻击之后,我想出了办法。它非常讨厌,但它确实有效。

如果我在WPF中,我会使用AlternationIndex并为索引0,1,2设置样式触发器,并将索引2的边框粗细设置为底部索引。

在Silverlight中,我们没有AlternationIndex OR样式触发器。所以,我不得不破解。我将代码包装成一个行为,所以我的XAML很干净:

Controls:DataGrid DataGridLines:HorizontalGridLineModulus.Index="3" ... />

支持它的代码如下所示:

public static class HorizontalGridLineModulus
{
    private static readonly DependencyProperty HorizontalGridLineModulusBehaviorProperty =
        DependencyProperty.RegisterAttached(
            "HorizontalGridLineModulusBehavior",
            typeof (HorizontalGridLineModulusBehavior),
            typeof (DataGrid),
            null);

    public static readonly DependencyProperty IndexProperty =
        DependencyProperty.RegisterAttached(
            "Index",
            typeof (int),
            typeof (HorizontalGridLineModulus),
            new PropertyMetadata(1, IndexChanged)
            );

    public static int GetIndex(DependencyObject dependencyObject)
    {
        return (int)dependencyObject.GetValue(IndexProperty);
    }

    public static void SetIndex(DependencyObject dependencyObject, int value)
    {
        dependencyObject.SetValue(IndexProperty, value);
    }

    private static void IndexChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var behavior = dependencyObject.GetValue(HorizontalGridLineModulusBehaviorProperty) as HorizontalGridLineModulusBehavior;
        if (behavior == null)
        {
            behavior = new HorizontalGridLineModulusBehavior(dependencyObject as DataGrid, (int)e.NewValue);
            dependencyObject.SetValue(HorizontalGridLineModulusBehaviorProperty, behavior);
        }
    }

}

public class HorizontalGridLineModulusBehavior
{
    private readonly DataGrid _grid;
    private readonly int _modulus;

    public HorizontalGridLineModulusBehavior(DataGrid grid, int modulus)
    {
        if(grid == null)
            throw new ArgumentException("grid");

        _grid = grid;
        _modulus = modulus;

        _grid.LayoutUpdated += GridLayoutUpdated;
    }

    private void GridLayoutUpdated(object sender, EventArgs e)
    {
        DrawBorders();
    }

    private void DrawBorders()
    {
        var presenter = _grid.Descendants<DataGridRowsPresenter>().FirstOrDefault();
        if(presenter == null) return;

        var orderedRows = presenter.Children.OrderBy(child => RowIndex(child));

        int count = 0;
        foreach (var row in orderedRows)
        {
            count++;
            var gridLine = row.Descendants<Rectangle>().Where(x => x.Name == "BottomGridLine").FirstOrDefault();

            if(gridLine != null)
                gridLine.Visibility = count % _modulus != 0 ? Visibility.Collapsed : Visibility.Visible;
        }
    }

    private static int RowIndex(UIElement element)
    {
        var row = element as DataGridRow;
        return row == null ? 0 : row.GetIndex();
    }
}

该代码使用了一些扩展方法,在这里定义:

public static class DependencyObjectExtensions
{
    public static IEnumerable<DependencyObject> Children(this DependencyObject element)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
            yield return VisualTreeHelper.GetChild(element, i);
    }

    public static IEnumerable<T> Children<T>(this DependencyObject element) where T : DependencyObject
    {
        return element.Children().Filter<T>();
    }

    public static IEnumerable<DependencyObject> Descendants(this DependencyObject element)
    {
        foreach (var child in element.Children())
        {
            yield return child;

            foreach (var descendent in child.Descendants())
                yield return descendent;
        }
    }

    public static IEnumerable<T> Descendants<T>(this DependencyObject element) where T : DependencyObject
    {
        return element.Descendants().Filter<T>();
    }

    public static IEnumerable<T> Filter<T>(this IEnumerable list) where T : class
    {
        foreach (var item in list)
        {
            if (item is T)
                yield return (T)item;
        }
    }
}