private void GenericLibraryExplorerItemControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            item = e.NewValue as GenericLibraryExplorerItem;

            if (null != item)
            {
                ObjCaption.Text       = String.Format("{0} ({1})", item.tag, item.fingerprints.Count);
                ObjCaption.Background = item.IsSelected ? ThemeColours.Background_Brush_Blue_VeryDarkToDark : Brushes.Transparent;
                ObjCaption.Foreground = item.IsSelected ? Brushes.Black : Brushes.Black;
                ObjChecked.IsChecked  = item.IsSelected;
            }
            else
            {
                ObjCaption.Text       = null;
                ObjCaption.Background = Brushes.Transparent;
                ObjCaption.Foreground = Brushes.Black;
                ObjChecked.IsChecked  = false;
            }
        }
        private void PopulateItems()
        {
            bool exclusive  = ObjBooleanAnd.IsChecked ?? true;
            bool is_negated = ObjBooleanNot.IsChecked ?? false;

            MultiMapSet <string, string> tags_with_fingerprints_ALL = GetNodeItems(this.library, null);
            MultiMapSet <string, string> tags_with_fingerprints     = tags_with_fingerprints_ALL;

            // If this is exclusive mode, we want to constrain the list of items in the tree
            if (!is_negated && exclusive && 0 < selected_tags.Count)
            {
                bool             first_set = true;
                HashSet <string> exclusive_fingerprints = new HashSet <string>();
                foreach (string selected_tag in selected_tags)
                {
                    if (first_set)
                    {
                        first_set = false;
                        exclusive_fingerprints.UnionWith(tags_with_fingerprints_ALL.Get(selected_tag));
                    }
                    else
                    {
                        exclusive_fingerprints.IntersectWith(tags_with_fingerprints_ALL.Get(selected_tag));
                    }
                }

                tags_with_fingerprints = GetNodeItems(this.library, exclusive_fingerprints);
            }

            // Filter them by the user filter
            List <string> tags_eligible = null;

            if (!String.IsNullOrEmpty(TxtSearchTermsFilter.Text))
            {
                string   filter_set = TxtSearchTermsFilter.Text.ToLower();
                string[] filters    = filter_set.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < filters.Length; ++i)
                {
                    filters[i] = filters[i].Trim();
                }

                tags_eligible = new List <string>();
                foreach (string tag in tags_with_fingerprints.Keys)
                {
                    string tag_lower = tag.ToLower();
                    foreach (string filter in filters)
                    {
                        if (tag_lower.Contains(filter))
                        {
                            tags_eligible.Add(tag);
                            break;
                        }
                    }
                }
            }
            else
            {
                tags_eligible = new List <string>(tags_with_fingerprints.Keys);
            }

            // Sort the tags
            List <string> tags_sorted = new List <string>(tags_eligible);

            if (ObjSort.IsChecked ?? false)
            {
                tags_sorted.Sort(delegate(string tag1, string tag2)
                {
                    return(tags_with_fingerprints[tag2].Count - tags_with_fingerprints[tag1].Count);
                });
            }
            else
            {
                tags_sorted.Sort();
            }

            // Create the tag list to bind to
            List <GenericLibraryExplorerItem> displayed_items = new List <GenericLibraryExplorerItem>();

            foreach (string tag in tags_sorted)
            {
                GenericLibraryExplorerItem item = new GenericLibraryExplorerItem
                {
                    GenericLibraryExplorerControl = this,
                    library = this.library,

                    tag          = tag,
                    fingerprints = tags_with_fingerprints[tag],

                    OnItemDragOver = this.OnItemDragOver,
                    OnItemDrop     = this.OnItemDrop,
                    OnItemPopup    = this.OnItemPopup,

                    IsSelected = selected_tags.Contains(tag)
                };

                displayed_items.Add(item);
            }

            // Bind baby bind - tag list
            TreeSearchTerms.DataContext = displayed_items;

            // Populate the chart
            PopulateChart(tags_with_fingerprints);

            // Then we have to list the associated documents
            HashSet <string> fingerprints = new HashSet <string>();

            if (0 < selected_tags.Count)
            {
                if (exclusive)
                {
                    bool first_set = true;
                    foreach (string selected_tag in selected_tags)
                    {
                        if (first_set)
                        {
                            fingerprints.UnionWith(tags_with_fingerprints.Get(selected_tag));
                        }
                        else
                        {
                            fingerprints.IntersectWith(tags_with_fingerprints.Get(selected_tag));
                        }
                    }
                }
                else
                {
                    foreach (string selected_tag in selected_tags)
                    {
                        fingerprints.UnionWith(tags_with_fingerprints.Get(selected_tag));
                    }
                }
            }

            // Implement the NEGATION
            if (is_negated && 0 < fingerprints.Count)
            {
                HashSet <string> negated_fingerprints = this.library.GetAllDocumentFingerprints();
                fingerprints = new HashSet <string>(negated_fingerprints.Except(fingerprints));
            }

            // And build a description of them
            // Build up the descriptive span
            Span descriptive_span = new Span();

            if (!String.IsNullOrEmpty(description_title))
            {
                Bold bold = new Bold();
                bold.Inlines.Add(description_title);
                descriptive_span.Inlines.Add(bold);
                descriptive_span.Inlines.Add(": ");
            }
            string separator = exclusive ? " AND " : " OR ";

            if (is_negated)
            {
                descriptive_span.Inlines.Add("NOT [ ");
            }
            descriptive_span.Inlines.Add(StringTools.ConcatenateStrings(selected_tags, separator, 0));
            if (is_negated)
            {
                descriptive_span.Inlines.Add(" ] ");
            }
            descriptive_span.Inlines.Add(" ");
            descriptive_span.Inlines.Add(LibraryFilterHelpers.GetClearImageInline("Clear this filter.", hyperlink_clear_all_OnClick));

            if (null != OnTagSelectionChanged)
            {
                OnTagSelectionChanged(fingerprints, descriptive_span);
            }
        }