Thursday, October 22, 2009

Silverlight Datagrid Layout Manager: The code

In the previous post I talked about a datagrid layout manager we used in our product. There is a demo and a link to code in that post as well. By the way, one thing I forgot to mention in that post: A user can drag/drop to rearrange the columns, and then if she opens "manage layout" and hit "save", the rearranged layout will persist to a future session. An added bonus.

Here is the the full demo, including user control and consuming code: http://www.filefactory.com/file/a06da5d/n/ContextMenuDemo_zip

I will try to break down the code in this post.

The column information in the datagrid is massaged into an ObservableCollection object. The definition for OrderedItem:



   1:      public class OrderedItem : INotifyPropertyChanged
   2:      {
   3:          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
   4:   
   5:          private string _Name;
   6:          public string Name
   7:          {
   8:              get { return _Name; }
   9:              set
  10:              {
  11:                  _Name = value;
  12:                  if (PropertyChanged != null)
  13:                  {
  14:                      PropertyChanged(this, new PropertyChangedEventArgs("Name"));
  15:                  }
  16:              }
  17:          }
  18:   
  19:          public string DisplayName { get; set; }
  20:          private int _Position;
  21:          public int Position
  22:          {
  23:              get { return _Position; }
  24:              set
  25:              {
  26:                  _Position = value;
  27:                  if (PropertyChanged != null)
  28:                  {
  29:                      PropertyChanged(this, new PropertyChangedEventArgs("Position"));
  30:                  }
  31:              }
  32:          }
  33:   
  34:          private bool _IsFrozen;
  35:          public bool IsFrozen
  36:          {
  37:              get { return _IsFrozen; }
  38:              set
  39:              {
  40:                  _IsFrozen = value;
  41:                  if (PropertyChanged != null)
  42:                  {
  43:                      PropertyChanged(this, new PropertyChangedEventArgs("IsFrozen"));
  44:                  }
  45:              }
  46:          }
  47:   
  48:          private bool _IsIncluded;
  49:          public bool IsIncluded
  50:          {
  51:              get { return _IsIncluded; }
  52:              set
  53:              {
  54:                  _IsIncluded = value;
  55:                  if (PropertyChanged != null)
  56:                  {
  57:                      PropertyChanged(this, new PropertyChangedEventArgs("IsIncluded"));
  58:                  }
  59:              }
  60:          }
  61:   
  62:          public OrderedItem Copy()
  63:          {
  64:              return new OrderedItem
  65:              {
  66:                  DisplayName = DisplayName,
  67:                  IsIncluded = IsIncluded,
  68:                  Name = Name,
  69:                  Position = Position
  70:              };
  71:          }
  72:   
  73:      }

This method examines the datagrid and creates the ObservableCollection:



   1:  public void ShowLayoutDialog()
   2:  {
   3:  LayoutRoot.Visibility = Visibility.Visible;
   4:  List<ordereditem> ls = new List<ordereditem>();
   5:  for (int i = ZeroBasedStartIndex; i < GridToFormat.Columns.Count; i++)
   6:              {
   7:                  var oi = new OrderedItem
   8:                  {
   9:                      Name = GridToFormat.Columns[i].Header.ToString(),
  10:                      Position = GridToFormat.Columns[i].DisplayIndex + 1 - ZeroBasedStartIndex,
  11:                      IsIncluded = (GridToFormat.Columns[i].Visibility == Visibility.Visible),
  12:                      IsFrozen = GridToFormat.Columns[i].IsFrozen
  13:                  };
  14:                  oi.PropertyChanged += new PropertyChangedEventHandler(OrderedItem_PropertyChanged);
  15:                  ls.Add(oi);
  16:              }
  17:              ls.Sort(new OrderedItemComparer());
  18:              ChooserGrid.ItemsSource = ls.ToObservableCollection<OrderedItem>();
  19:  }

Here is the method that applies the layout to the grid. InitLayout() and the Save-click handler method calls this method to do their heavy lifting.



   1:          private void UpdateGridLayout(OrderedItem[] layouts)
   2:          {
   3:              try
   4:              {
   5:                  if (layouts != null)
   6:                  {
   7:                      int fc = (from l in layouts where l.IsFrozen select 1).Count();
   8:                      GridToFormat.FrozenColumnCount = (fc > 0) ? fc + ZeroBasedStartIndex : 0;
   9:                      foreach (OrderedItem layout in layouts)
  10:                      {
  11:                          foreach (DataGridColumn c in GridToFormat.Columns)
  12:                          {
  13:                              if (c.Header.ToString() == layout.Name)
  14:                              {
  15:                                  c.Visibility = layout.IsIncluded ? Visibility.Visible : Visibility.Collapsed;
  16:                                  c.DisplayIndex = layout.Position - 1 + ZeroBasedStartIndex;
  17:                                  break;
  18:                              }
  19:                          }
  20:                      }
  21:                  }
  22:                  else
  23:                  {
  24:                      for (int i = ZeroBasedStartIndex; i < GridToFormat.Columns.Count; i++)
  25:                      {
  26:                          GridToFormat.Columns[i].DisplayIndex = i;
  27:                          GridToFormat.Columns[i].Visibility = Visibility.Visible;
  28:                      }
  29:                  }
  30:              }
  31:              catch
  32:              {
  33:                  UpdateGridLayout(null);
  34:                  _AppSettings[AppKey] = null;
  35:                  _AppSettings.Save();
  36:              }
  37:          }

There are other methods that handle PropertyChanged event for the OrderedItem, and to handle user actions to movver the item up or down. I just want to point out what each method did, and I think the xaml and cs code (that can be downloaded from link in previous post) are pretty self-explanatory. I hope this gives you enough info about the the guts of the user-control to tweak it to your liking.

No comments:

Post a Comment