public Search()
        {
            InitializeComponent();
            Loaded += Search_Loaded;
            _selectionBackgroundBinding = new Binding("HighlightBackground");
            _selectionForegroundBinding = new Binding("HighlightForeground");
            _defaultForegroundBinding = new Binding("DefaultForeground");
            _selectedResultsItem = null;

            KeyDown += Search_KeyDown;
            KeyUp += Search_KeyUp;
        }
        public Navigation()
        {
            InitializeComponent();

            Loaded += Navigation_Loaded;
            _selectionBackgroundBinding = new Binding("HighlightBackground");
            _selectionForegroundBinding = new Binding("HighlightForeground");
            _defaultForegroundBinding = new Binding("DefaultForeground");
            _selectedContentsItem = null;

            _resetCurrentPositionToHeading = true;

            KeyDown += Navigation_KeyDown;
            KeyUp += Navigation_KeyUp;
        }
        private void searchResultsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //if(searchResultsListBox != null) //Need to focus the parent listbox
            //    searchResultsListBox.Focus();

            if(searchResultsListBox.SelectedIndex > -1)
            {
                ExtendedListBoxItem currentItem = searchResultsListBox.SelectedItem as ExtendedListBoxItem;

                if(currentItem != null)
                {
                    //Remove highlighting from the previously selected item.
                    if(_selectedResultsItem != null)
                    {
                        _selectedResultsItem.SetBinding(ForegroundProperty, _defaultForegroundBinding);
                    }

                    currentItem.SetBinding(ForegroundProperty, _selectionForegroundBinding);
                    _selectedResultsItem = currentItem;
                }

                SearchSelected(sender, new ItemSelectedEventArgs(SearchResults[searchResultsListBox.SelectedIndex].ID));
            }
        }
        /// <summary>
        /// Updates the list of search results when the SearchResults property is set.
        /// </summary>
        private void PopulateSearchResults()
        {
            searchResultsListBox.Items.Clear();
            Style listItemStyle = Application.Current.Resources[Strings.ListItemStyleKey] as Style;

            if(SearchResults == null || SearchResults.Count == 0)
            {
                TextBlock noResults = new TextBlock();
                noResults.Text = "No search results found.";
                resultsHeader.Text = "Results:";

                ExtendedListBoxItem newItem = new ExtendedListBoxItem();
                newItem.Content = noResults;
                AutomationProperties.SetHelpText(newItem, "No results found for this search, please go back and try a different search.");
                searchResultsListBox.Items.Add(newItem);
                if(IndicateSearchResultsChanged != null)
                {
                    IndicateSearchResultsChanged(this, new EventArgs());
                }

                SelfVoicingSpeakText(this, new SpeechTextEventArgs(noResults.Text));
                return;
            }

            //Populate the search results box
            foreach(SearchResult result in SearchResults)
            {
                //Construct ListBoxItem from textblock of multiple runs
                ExtendedListBoxItem currentItem = new ExtendedListBoxItem();
                currentItem.Style = listItemStyle;
                currentItem.SetBinding(ExtendedListBoxItem.SelectionBackgroundProperty, _selectionBackgroundBinding);
                currentItem.SetBinding(ForegroundProperty, _defaultForegroundBinding);

                TextBlock displayedResult = new TextBlock();

                int currentIndex = 0;

                while(currentIndex < result.Text.Length)
                {
                    // get the next occurance of the search string in the search result
                    int nextSearchStringIndex = result.Text.Substring(currentIndex).ToLower().IndexOf(result.SearchString.ToLower());

                    if(nextSearchStringIndex == -1)
                    {
                        break;
                    }

                    // construct a run for the text leading up to the match
                    if(currentIndex != nextSearchStringIndex)
                    {
                        Run preSearchWord = new Run();
                        preSearchWord.Text = result.Text.Substring(currentIndex, nextSearchStringIndex);
                        displayedResult.Inlines.Add(preSearchWord);
                    }

                    //if (nextSearchStringIndex)
                    Run SearchWord = new Run();

                    SearchWord.Text = result.Text.Substring(currentIndex + nextSearchStringIndex, result.SearchString.Length);
                    SearchWord.FontWeight = FontWeights.Bold;
                    displayedResult.Inlines.Add(SearchWord);

                    currentIndex += (nextSearchStringIndex + result.SearchString.Length);
                }

                Run postSearchWord = new Run();

                if(currentIndex != result.Text.Length)
                {
                    postSearchWord.Text = result.Text.Substring(currentIndex);
                    displayedResult.Inlines.Add(postSearchWord);
                }

                displayedResult.TextWrapping = TextWrapping.Wrap;
                currentItem.Content = displayedResult;
                AutomationProperties.SetHelpText(currentItem, result.Text + ". Use the up and down arrow keys to scroll through the other search results.");

                //We don't want to have to tab through all of the search result items, since up and down already do that
                currentItem.TabNavigation = KeyboardNavigationMode.Once;
                currentItem.IsTabStop = false;

                searchResultsListBox.Items.Add(currentItem);
            }

            searchResultsListBox.InvalidateMeasure();
            if(IndicateSearchResultsChanged != null)
            {
                IndicateSearchResultsChanged(this, new EventArgs());
            }

            //TODO: Distinguish plural and singular (i.e. result from results)
            resultsHeader.Text = String.Format("Results: ({0} results found)", SearchResults.Count);

            SelfVoicingSpeakText(this, new SpeechTextEventArgs(string.Format(Speech.ResultsFoundMessage, SearchResults.Count)));
        }
        /// <summary>
        /// Navigate the book to the given heading index of the table of contents when a TOC heading
        /// is selected.
        /// </summary>
        /// <remarks>NOTE: Currently there is no unwiring of this event when the TOC is updated,
        ///  so it may be triggered when the list is repopulated.
        /// </remarks>
        private void TableOfContentsListBox_SelectionChanged(object sender, SelectionChangedEventArgs args)
        {
            ListBox targetListBox = sender as ListBox;

            if(targetListBox != null) //Need to focus the parent listbox
                targetListBox.Focus();

            // When the listbox is first being populated the selected item could be null.
            if(targetListBox.SelectedItem != null)
            {
                //Remove highlightin from the previously sleected item.
                if(_selectedContentsItem != null)
                {
                    _selectedContentsItem.SetBinding(ForegroundProperty, _defaultForegroundBinding);
                }

                //Highlight the current item & save reference
                ExtendedListBoxItem currentItem = targetListBox.SelectedItem as ExtendedListBoxItem;

                currentItem.SetBinding(ForegroundProperty, _selectionForegroundBinding);
                //Ensure the element is scrolled into view.
                if(ParentViewer != null)
                    currentItem.ScrollIntoView(ParentViewer, DisplayAttributes.CommonInstance.VisualScale);

                _selectedContentsItem = currentItem;

                // set the selected item args to the toc id and raise event
                int SelectedHeadingID = (targetListBox.SelectedIndex);
                NavigateToHeadingID(SelectedHeadingID);
            }
        }
        /// <summary>
        /// Refreshes the items displayed in the Table of Contents. Called when the TOC reference is (re)set.
        /// </summary>
        private void PopulateTableOfContents()
        {
            // empty out the table of contents listbox and render new table of contents
            TableOfContentsListBox.SelectedItem = null;
            TableOfContentsListBox.Items.Clear();

            foreach(Heading heading in _tableOfContents.FlatHeadingList)
            {
                var newItem = new ExtendedListBoxItem();
                if(Application.Current.Resources.Contains(Strings.ListItemStyleKey))
                {
                    newItem.Style = Application.Current.Resources[Strings.ListItemStyleKey] as Style;
                }
                newItem.SetBinding(ExtendedListBoxItem.SelectionBackgroundProperty, _selectionBackgroundBinding);
                newItem.SetBinding(ForegroundProperty, _defaultForegroundBinding);
                newItem.Content = heading.Text;
                // margin for header, set as multiple of level, currently fixed indentation size
                newItem.Margin = new Thickness(heading.level * 15, 0, 0, 0);
                newItem.Padding = new Thickness(0, 0, 0, 0);
                newItem.Height = 20;

                //Set the automation name for each list box item
                AutomationProperties.SetAutomationId(newItem, heading.Text);
                AutomationProperties.SetHelpText(newItem, heading.Text + ". Use the up and down arrow keys to scroll through the other headings in this book.");
                //newItem.GotFocus += SpeakControlOnFocus;

                TableOfContentsListBox.Items.Add(newItem);
            }
            if(IndicateSearchResultsChanged != null)
            {
                IndicateSearchResultsChanged(this, new EventArgs());
            }

            //Reset to first heading.
            SelectedElement = 0;
        }