Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Grid Row Iteration

0.00/5 (No votes)
19 Oct 2012 1  
How to iterate a WPF Grid control's rows.

Introduction

Do you need to iterate a WPF <Grid> control's row collection? This code shows you how to do that by "dropping" down to a more fundamental layer of WPF's UIElement layer. On the way "down there", the VisualTreeHelper class is used to find the children to the <Grid> rows.

Background

DataGrids, DataGridViews and other data controls, classes, and collections all allow row iteration using built-in methods. The WPF <Grid> control does not have this function. This article shows how to create a <Grid> row iterator to access the text content of each row.

Using the Code

A helper class to iterate the "Visual" component of the <Grid> control is in order. Look at this as the HTMLElement equivalent in WPF. We want the individual UIElements of the Grid. Once we have them, getting the Value of each element is simple.

This static Iterate helper method below uses the VisualTreeHelper to iterate the "Visual Tree" of WPF. Notice the it accepts a delegate EnumVisualCallBack named "cb".

public static void Iterate(Visual visual, EnumVisualCallBack cb)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
    {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(visual, i);
        cb(childVisual);
        // Enumerate children of the child visual object.
        Iterate(childVisual, cb);
    }
}

The delegate lives at the namespace level for each cross-class access, and looks like this: delegate void EnumVisualCallBack(Visual visual);.

The delegate signature is simply looking for a method that returns void and accepts a Visual. The reason the design is done like this is for the sake of the caller of Iterate. The caller can implement their own logic in their class and leave the iteration up to someone else.

The callback code is shown below, and is placed in the portion of code that needs to iterate the <Grid>.

private StringBuilder sb = null;
public void VisualCallBack(Visual visual) {
 if (visual.GetType().Name == "ContentPresenter") return;
  UIElement uie = (UIElement)visual;
  System.Reflection.PropertyInfo[] pi = uie.GetType().GetProperties();
  var stuff = from q in pi.OfType<System.Reflection.PropertyInfo>()
                  where q.Name=="Content" 
  select q;
  foreach (System.Reflection.PropertyInfo pi2 in stuff) {
     sb.Append(pi2.GetValue(uie, null).ToString()) ;
 }
}

We now have the Iterator and the callback to process the iteration, so how do we invoke all of this? Assuming you have a button that will copy a <Grid> content to the clipboard in the Click event, the code would look like this:

private void b_Copy_Click(object sender, RoutedEventArgs e)
{
  Grid temp = SomeGrid;
  EnumVisualCallBack cb = new EnumVisualCallBack(VisualCallBack);
  sb = new StringBuilder();
  //Iteratate the grid, and call the cb on each iteration.
  EnumVisual.Iterate(temp, cb);
  //Copy everything you have in string builder to ClipBoard
  Clipboard.SetText(sb.ToString());
}

Points of Interest

Using callbacks for iteration is good because it allows you to keep the "code once" mantra. It also add immense flexibility in the callback logic because there could be as many variations as needed to process that data in anyway necessary. All of this while maintaining a never changing iterator.

The filter in the callback to reject types of "ContentPresenter" stops duplicate iterations; as the VisualTreeHelper will find the ContentPresenter as well as the content within, we don't want the presenter, just the content.

Using the PropertInfo class, we call the GetValue method which is similar to an HTMLElement GetValue call. All we want is the value of the property which is named "Content"...

So why didn't WPF have a built in for <Grid> row iteration? Don't know...

History

  • 19/Oct/2012- Fixed Code download link
  • 30/Jul/2010 - Version 1.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here