Group Descriptions

groupdescriptionsimage.png

Group Descriptions can be applied to both ListBox and/or ListView IParents and allow for categorization.

The categories or groupings in WPF for Group Descriptions are typically defined via Databinding. However, in WPF Composites, groupings may be defined based on XY (row-column) coordinates via the SetGroupItemConverter:

//1. Group on Text in a Composite at 1, 0
.SetGroupItemConverter(
composite =>
    { 
return 
(composite.GetChildFromComposite<TextBlock, ListView>(1, 0)).GetText().ToString(); 
     }
) 

Group Descriptions are originally defined in the settings of the ListBox or ListView. Besides defining the groupings, you must also define what the "look and feel" of the groupings will be by defining both a GroupItem (typically a Label) and a GroupExpander via FrameworkElementFactories. These FrameworkElementFactories allow creating ControlTemplates on-the-fly behind-the-scenes to be applied to the GroupItem and GroupExpander respectively.

Here is a full code example:
myListView.BeginSettings<ListView>()
     .SetBackgroundColorOnItemsControl(BrushExt.CreateGradientBrush("#DDDDDD", 25, "#33AAFF", 25, 1, 50, 1, 50)) //

     //1. Group on Text in a Composite at 1, 0
    .SetGroupItemConverter(composite =>
          { return (composite.GetChildFromComposite<TextBlock, ListView>(1, 0)).GetText().ToString(); }) 

    //2. Define Group Item -- the label for the display of groupings (to display Group Name and Item Count)
   .SetGroupItemFrameworkElementFactory(new FrameworkElementFactory(typeof(Label))
         .SetProperty(Label.FontWeightProperty, FontWeights.Bold)
         .SetProperty(Label.MarginProperty, new Thickness(5, 0, 0, 0))
         .SetProperty(Label.HeightProperty, 54.0D)
         .SetProperty(Label.WidthProperty, 234.0D)
         .SetProperty(Label.FontSizeProperty, 17.0)
         .SetProperty(Label.BackgroundProperty, Brushes.Green)
         .SetProperty(Label.BorderBrushProperty, Brushes.Black)
         .SetProperty(Label.BorderThicknessProperty, new Thickness(1))
         .SetProperty(Label.HorizontalAlignmentProperty, HorizontalAlignment.Left)
         .SetProperty(Label.ContentProperty, new Binding() { Path = new PropertyPath("Tag"), RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Expander), 1) }))

    //3. Define Group Expander
   .SetGroupExpanderFrameworkElementFactory(new FrameworkElementFactory(typeof(Expander))
        .SetProperty(Expander.IsExpandedProperty, true)
        .SetProperty(Expander.BorderBrushProperty, Brushes.Blue)
        .SetProperty(Expander.TemplateProperty, ExpanderExt.ApplyExpanderStrategyFull("Navy", "Blue", "Blue", "Purple", "Green", "Gold", "Transparent", "M0,0 L0,5 L5,0 z", "M5,5 L0,5 L5,0 z", ExpanderExt.Shape.Rectangle))
        .SetProperty(Expander.BorderThicknessProperty, new Thickness(0, 0, 0, 1)))

Helper methods exist to make this more concise, such as in this ListBox example:
myListBox.BeginSettings<ListBox>()
   .SetBackgroundColorOnItemsControl(BrushExt.CreateGradientBrush("#DDDDDD", 25, "#33AAFF", 25, 1, 50, 1, 50))
                
   //1. Group on Text in a Composite at 1, 0
   .SetGroupItemConverter(composite =>
                { return (composite.GetChildFromComposite<TextBlock, ListBox>(1, 0)).GetText().ToString(); }) 

   //2. Define Group Item -- the label for the display of groupings (to display Group Name and Item Count)
.SetGroupItemFrameworkElementFactory(ContemporaryStyle.CreateLabelForGroupItem(54.0D, 234.0D, 17.0D, FontWeights.Bold, new Thickness(5, 0, 0, 0), Brushes.Black, Brushes.AliceBlue, Brushes.Black, new Thickness(1), HorizontalAlignment.Left))

   //3. Define Group Expander
.SetGroupExpanderFrameworkElementFactory(ContemporaryStyle.CreateExpanderForGroupItem(null, true, Brushes.Blue, new Thickness(0, 0, 0, 1), "White", "White", "Gold", "Gold", "Yellow", "Yellow", "DarkBlue", ExpanderExt.Shape.Ellipse))

There is a fourth step as well that may be necessary. The Selected Item Color when an item is clicked may be lost when using Group Descriptions; therefore, you may need to add this extra code to manually set the color of a selected item:
  //4. When using GroupExpander handle setting selected Border manually
  .SubscribeMouseSingleClickOnBorder((o, ev) =>
       {
             manuallySetSelectedColor<ListBox>(o);
       })

       . . . . . .

private static void manuallySetSelectedColor<T>(object o)
       where T: ListBox
{
        var cc1 = ((Border)o).Child as ContentControl;
        var lv1 = cc1.Tag as T;
        lv1.SelectedItem = ((Border)o);

        Dictionary<string, object> dict = lv1.GetCompositeLookupDictionary();

        foreach (KeyValuePair<string, object> keyval in dict)
        {
             (keyval.Value as Border).Background = Brushes.Transparent;  //set everyone else to Transparent
        }

        ((Border)o).Background = Brushes.PowderBlue; //set selected to Powder Blue
}

Moreover, when using Group Descriptions, upon initially loading a screen, you may want to Select the First Item (if one exists) in the ListBox or ListView. Here is an example of this below which you may notice shares much of the same code as the snippet above:

#region Select a first item. When using Group Descriptions, set selected Border manually
var compLkp = myListBox.GetCompositeLookupDictionary();
Border starterItem = (compLkp.First<KeyValuePair<string, object>>()).Value as Border;
myListBox.SelectedItem = ((Border)starterItem);

Dictionary<string, object> dictStart = myListBox.GetCompositeLookupDictionary();

foreach (KeyValuePair<string, object> keyval1 in dictStart)
{
      (keyval1.Value as Border).Background = Brushes.Transparent; //set everyone else to Transparent
}

((Border)starterItem).Background = Brushes.PowderBlue; //set selected to Powder Blue
#endregion

Finally, you may desire to update the "look and feel" of the groupings on-the-fly via updating the GroupStyle. Here is the code example:

 #region Add New Group Item Label and Group Expander Style

FrameworkElementFactory factoryLabel = ContemporaryStyle.CreateLabelForGroupItem(34.0D, 334.0D, 17.0D, FontWeights.Bold, new Thickness(5, 0, 0, 0), Brushes.Orange, Brushes.AliceBlue, Brushes.Red, new Thickness(1), HorizontalAlignment.Left);

FrameworkElementFactory factoryExpander = ContemporaryStyle.CreateExpanderForGroupItem(factoryLabel, isExpanded, Brushes.Green, new Thickness(0, 0, 0, 1), "Orange", "Red", "Blue", "Purple", "Green", "Gold", "Transparent", "M0,0 L0,5 L5,0 z", "M5,5 L0,5 L5,0 z", ExpanderExt.Shape.Rectangle);

Style myStyle = ContemporaryStyle.CreateStyleForGroupItem(factoryExpander, new Thickness(1));

GroupStyle groupStyle = new GroupStyle();
groupStyle.ContainerStyle = myStyle;
myListView.GroupStyle.Clear();
myListView.GroupStyle.Add(groupStyle);

#endregion

Last edited Mar 2, 2014 at 1:22 AM by stagathome0069, version 22

Comments

No comments yet.