Another great service, provided by Windows Vista is it's integrated search. Can we use it from our WPF application? Sure we can. This how you'll do it.
First of all you'll need to find Windows Search API library inside Windows SDK. Locate SearchAPI.tlb and process it with tlbimp tool to create managed assembly to reference to. You'll get file, named SeachAPILib.dll. This one, you need. In order to use it, refer to MSDN documentation of Windows Search API 3.0. Actually, using of search API is not much different then using database queries. However, this is not so trivial in core. Actually, the syntax of Windows Search (AQS - Advanced Query Syntax) is very different. But search team create brilliant work to make our life easier. CSearchManager and ISeachQueryHelper - those translate AQS to SQL and, even provide us with proper connection string.
Let's start. First of all, we'll have to create CSeachManager
CSearchManager cManager = new CSearchManagerClass();
</PRE< P>
Then, while you are in query, you'll create new ISearchQueryHelper to help you with translations and query strings
ISearchQueryHelper cHelper = cManager.GetCatalog("SYSTEMINDEX").GetQueryHelper();
cHelper.QuerySelectColumns = "\"System.ItemNameDisplay\"";</PRE< P>
Well done, now. Ask Vista with old good OleDB provider
using (cConnection = new OleDbConnection(
cHelper.ConnectionString))
{
cConnection.Open();
using (OleDbCommand cmd = new OleDbCommand(
cHelper.GenerateSQLFromUserQuery(
SearchString
),
cConnection))
{
if (cConnection.State == ConnectionState.Open)
{
using (OleDbDataReader reader = cmd.ExecuteReader())
{
m_results.Clear();
while (!reader.IsClosed && reader.Read())
{
m_results.Add(reader[0].ToString());
}
reader.Close();
}
}
}
cConnection.Close();
}</PRE< P>
Brilliant. Let's move it into WPF by creating DependencyObject, that provide us with all we need for search - search string and array of results
public static readonly DependencyProperty SearchTextProperty = DependencyProperty.Register("SearchText", typeof(string), typeof(VistaSearchProviderHelper), new UIPropertyMetadata(default(string),
new PropertyChangedCallback(OnSearchTextChanged)));
static void OnSearchTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//change
ToAbortFlag = IsWorkingFlag;
if (workerCallback == null)
workerCallback = new WaitCallback(doSearch);
searchObjState.SearchString = e.NewValue.ToString();
//if (searchObjState.SearchString.Length > 2)
{
workerCallback.BeginInvoke(searchObjState, null, null);
}
}</PRE< P>
public string SearchText
{
get { return GetValue(SearchTextProperty).ToString(); }
set { SetValue(SearchTextProperty, value); }
}
static ThreadSafeObservableCollection<string> m_results;
public ReadOnlyObservableCollection<string> Results
{
get { return new ReadOnlyObservableCollection<string>(m_results); }
}</PRE< P>
I think you know where to get thread safe observable collection :)
The only thing we should do now is to bind input and output to XAML presentation
<StackPanel FocusManager.FocusedElement="{Binding ElementName=searchStr}">
<StackPanel.DataContext>
<ObjectDataProvider ObjectType="l:VistaSearchProviderHelper"/>
</StackPanel.DataContext>
<TextBox Name="searchStr" Text="{Binding Path=SearchText, UpdateSourceTrigger=PropertyChanged }" FontSize="30"/>
<ListBox ItemsSource="{Binding Path=Results}" />
</StackPanel></PRE< P>
We done. Now we can search our Windows Vista from custom WPF application. This is not final application for sure, there is a long way to go to make it work perfectly, but this is the beginning of how to do it.
1 comment:
Hi ,
I am trying to have a search field and a drop down box and a search button , based on the values in search field and drop down box i press the search button to make an api call to get the results . Now I have a listview where i want to be able to display the results using the Observable Collection. Can you help me with a possible solution.
Post a Comment