Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Highlight the result from context sensitive search in windows phone 7?

I need to to Highlight the search result according to the text that is entered in the text box in windows phone 7,

enter image description here

the usual wpf code is not working in windows phone 7. . Somebody say how to achieve this in windows phone 7

Actually this is the xaml Listbox I'm using to populate the Contact list,

    <ListBox Name="ContactList" ItemsSource="{Binding}" Margin="14,85,14,28" Foreground="White" SizeChanged="ContactList_SizeChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Border BorderThickness="2" HorizontalAlignment="Left" VerticalAlignment="Center" BorderBrush="{StaticResource PhoneAccentBrush}" >
                            <Image Source="{Binding Converter={StaticResource ContactPictureConverter}}" Width="48" Height="48" Stretch="Fill" Name="img1" />
                        </Border>
                        <TextBlock Name="ContactResults" Text="{Binding Path=DisplayName, Mode=OneWay}" FontSize="{StaticResource PhoneFontSizeExtraLarge}" Margin="18,8,0,0" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <TextBox Name="contactFilterString" Margin="0,0,0,528" TextChanged="contactFilterString_TextChanged" />

C# Code,

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    //using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.UserData;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Collections.ObjectModel;
    using Microsoft.Phone.Shell;
    using System.Windows.Controls;
    using System.Windows.Media.Imaging;
    using System.Text.RegularExpressions;

    namespace SmartContactsApp
    {
public partial class MainPage : PhoneApplicationPage
{
    private List<Address> lstAddress = new List<Address>();
    public string addressJson = string.Empty;

    // Constructor
    public MainPage()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        CreateSecondaryTile();
    }

    /// <summary>
    /// To List all the Contacts. . .
    /// </summary>
    private void ContactListing()
    {
        ContactList.DataContext = null;
        Contacts cons = new Contacts();
        cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
        cons.SearchAsync(contactFilterString.Text, FilterKind.DisplayName, "Contacts");
    }

    /// <summary>
    /// To Fetch All Contacts from Mobile Contacts. . .
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
    {
        try
        {
            ContactList.DataContext = e.Results;

        }
        catch (Exception)
        {
            throw;
        }
    }

    private void contactFilterString_TextChanged(object sender, TextChangedEventArgs e)
    {
        ContactListing();
    }
    }

How to highlight in this,

Thanks in advance!

like image 553
Gopinath Perumal Avatar asked Dec 22 '12 06:12

Gopinath Perumal


2 Answers

I Did it with the help from this

Xaml code:

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <ListBox Name="ContactList" Margin="14,85,14,28" Foreground="White">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding DisplayName}" Width="450" TextWrapping="Wrap" FontSize="24" Visibility="Collapsed"/>
                        <RichTextBox Width="450" FontSize="24" Foreground="#FFFFFF"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <TextBox Name="contactFilterString" Margin="0,0,0,528" TextChanged="contactFilterString_TextChanged" />
    </Grid>

c# Code:

            private void contactFilterString_TextChanged(object sender, TextChangedEventArgs e)
    {
       // ContactListing();
        SearchVisualTree(ContactList);
        if (contactFilterString.Text == "")
        {
            ContactListing();
        }
    }

    private void SearchVisualTree(Action ContactListing)
    {
        SearchVisualTree(ContactList);
    }

    private void SearchVisualTree(DependencyObject targetElement)
    {

        var count = VisualTreeHelper.GetChildrenCount(targetElement);

        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(targetElement, i);
            if (child is TextBlock)
            {
                textBlock1 = (TextBlock)child;
                HighlightText();
                break;
            }
            else
            {
                //ContactListing();
                SearchVisualTree(child);
            }
        }
    }

    private void HighlightText()
    {
        if (textBlock1 != null)
        {
            string text = textBlock1.Text;
            textBlock1.Text = text;
            textBlock1.Inlines.Clear();

            int index = text.IndexOf(contactFilterString.Text);
            int lenth = contactFilterString.Text.Length;


            if (!(index < 0))
            {
                Run run = new Run() { Text = text.Substring(index, lenth), FontWeight = FontWeights.ExtraBold };
                run.Foreground = new SolidColorBrush(Colors.Orange);
                textBlock1.Inlines.Add(new Run() { Text = text.Substring(0, index), FontWeight = FontWeights.Normal });
                textBlock1.Inlines.Add(run);
                textBlock1.Inlines.Add(new Run() { Text = text.Substring(index + lenth), FontWeight = FontWeights.Normal });

                textBlock1.FontSize = 30;
                textBlock1.Foreground = new SolidColorBrush(Colors.Black);
            }
            else
            {
                //textBlock1.Text = "No Match";

            }
        }

    }

     /// <summary>
    /// To List all the Contacts. . .
    /// </summary>
    private void ContactListing()
    {
        ContactList.DataContext = null;
        Contacts cons = new Contacts();
        cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
        cons.SearchAsync(contactFilterString.Text, FilterKind.DisplayName, "Contacts");
    }

    /// <summary>
    /// To Fetch All Contacts from Mobile Contacts. . .
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
    {
        try
        {

            ContactList.DataContext = e.Results;

        }
        catch (Exception)
        {
            throw;
        }
    }

Thanks for the help!

like image 87
Gopinath Perumal Avatar answered Oct 22 '22 10:10

Gopinath Perumal


For a similar kind of requirement, I did the following:

First I took the following as part of my ListBox data template

<StackPanel Width="450">
    <TextBlock Text="{Binding text}" Width="450" TextWrapping="Wrap" FontSize="24" Visibility="Collapsed"/>
    <RichTextBox Width="450" FontSize="24" Foreground="#FFFFFF"/>
</StackPanel>

Then in the code behind: The list which I am using to bind to the ListBox is defined as follows

 public List<Result> results {
        get
        {  
            return _results;
        }
        set
        {
            string x = null;
            foreach (var item in value)
            {
                item.text2 = item.text;
                if (!item.text.StartsWith("<Section"))
                    if(!item.text.Contains("</Run>"))
                {
                    String xamlData = null;
                    var regx = new Regex(@query.Trim(), RegexOptions.IgnoreCase);
                    var matcches = regx.Matches(item.text);
                    x += matcches.Count;
                    if (matcches.Count > 0)
                    {
                        var match = @query.Trim();
                        xamlData = Regex.Replace(item.text, match, "<Run Foreground="Blue" FontWeight=\"ExtraBold\">" + match + "</Run>", RegexOptions.IgnoreCase);
                    }
                    if (xamlData == null)
                        xamlData = item.text;
                    item.text = "<Section xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"><Paragraph>" + xamlData + "</Paragraph></Section>";
                }
            }
            _results = value;
        }
    }

Then after getting the search results, add those to the above list and then setting it as the ItemsSource for the ListBox.

Now comes the critical part of the ListBox. Add a listbox_SizeChanged event handler as shown below

private void listboxMyTimeline_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        for (int i = 0; i < listboxMyTimeline.Items.Count; i++)
        {
            ListBoxItem lbi2 = (ListBoxItem)(listboxMyTimeline.ItemContainerGenerator.ContainerFromIndex(i));
            if (lbi2 != null)
            {
                var ob = FindFirstElementInVisualTree<RichTextBox>(lbi2);
                var ob2 = FindFirstElementInVisualTree<TextBlock>(lbi2);
                ob.Xaml = ob2.Text;
            }
            else
            {
                var itm = listboxMyTimeline.Items.ElementAt(i);
                lbi2 = (ListBoxItem)(listboxMyTimeline.ItemContainerGenerator.ContainerFromItem(itm));
                if (lbi2 != null)
                {
                    var ob = FindFirstElementInVisualTree<RichTextBox>(lbi2);
                    var ob2 = FindFirstElementInVisualTree<TextBlock>(lbi2);
                    ob.Xaml = ob2.Text;
                }
            }
        }
    }

Where the FindFirstElementVisualTree method is like this

private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
    {
        var count = VisualTreeHelper.GetChildrenCount(parentElement);
        if (count == 0)
            return null;

        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(parentElement, i);

            if (child != null && child is T)
            {
                return (T)child;
            }
            else
            {
                var result = FindFirstElementInVisualTree<T>(child);
                if (result != null)
                    return result;

            }
        }
        return null;
    }

So, I am taking a hidden text box to which I am binding the actual text's constructed XAML code. This is because you cannot directly bind to the RichTextBox or Run elements. Then In the Size_changed handler, I am setting that XAMl code to the visible RichTextBox.

I am not sure to what extent it suits your needs, you may need to make many changes to the above process inorder to make it work for you.

Good luck :)

UPDATE:

Replace the Result class in my code with the Address class in your code.

And Replace your List definition with my List.

Add an additional property called 'xamlCode' in your Address class. (Replace the item.text2 = item.text line as item.xamlCode = item.DisplayName

And the rest should be clear for you.

Still if any doubts, Ask here.

like image 1
nkchandra Avatar answered Oct 22 '22 10:10

nkchandra