The viewmodel uses the IEbayClient
instance to query the eBay OData service. The viewmodel exposes two commands:
SearchCommand—Triggered by entering text into a TextBox
in the view, this command calls the Search
method, which calls the IEbayClient
’s SearchItemsAsync
method.
FetchMoreDataCommand—This command allows the search results to be paged.
The commands are initialized in the EbaySearchViewModel
constructor, which is shown in the following excerpt:
public EbaySearchViewModel(
Func<IEbayClient> getEbayClientFunc,
INetworkConnectionMonitor networkConnectionMonitor)
{
this.networkConnectionMonitor = ArgumentValidator.AssertNotNull(
networkConnectionMonitor, "networkConnectionMonitor");
this.getEbayClientFunc = ArgumentValidator.AssertNotNull(
getEbayClientFunc, "getEbayClientFunc");
networkConnectionMonitor.NetworkConnectionChanged
+= (sender, args) => UpdateCommands();
SearchText = "star wars action figure";
searchCommand = new DelegateCommand<string>(
query =>
{
if (!string.IsNullOrEmpty(query))
{
Search(query);
}
}, obj => networkConnectionMonitor.Connected);
fetchMoreDataCommand = new DelegateCommand(
obj =>
{
if (!string.IsNullOrEmpty(lastQuery))
{
Search(lastQuery, true);
}
}, obj => networkConnectionMonitor.Connected);
}
The enabled state of each command depends on the Connected
property of the INetworkConnectionMonitor
. When the NetworkConnectionChanged
event is raised, the viewmodel’s UpdateCommands
method is called, which calls the RaiseCanExecuteChanged
method on each command, causing the Enabled
state to be reevaluated:
void UpdateCommands()
{
searchCommand.RaiseCanExecuteChanged();
fetchMoreDataCommand.RaiseCanExecuteChanged();
}
The viewmodel’s Search
method uses a Func
named getEbayClientFunc
to retrieve an IEbayClient
(see Listing 27.5). The Search
method sets the viewmodel’s Busy
property to true, causing a ProgressBar
in the view to be made visible.
To reduce the amount of data retrieved from the OData service, the number of records retrieved by the IEbayClient
is restricted to 10.
const int chunkSize = 10;
string lastQuery;
bool appendResult;
void Search(string query, bool append = false)
{
if (lastQuery == query && Busy)
{
return;
}
lastQuery = query;
appendResult = append;
IEbayClient ebayClient = getEbayClientFunc();
ebayClient.SearchItemsComplete -= HandleEbayClientSearchItemsComplete;
ebayClient.SearchItemsComplete += HandleEbayClientSearchItemsComplete;
int beginIndex = appendResult ? Items.Count : 0;
try
{
Busy = true;
ebayClient.SearchItemsAsync(query, beginIndex, chunkSize);
}
catch (Exception ex)
{
Busy = false;
Console.WriteLine("Unable to perform search." + ex);
MessageService.ShowError("Unable to perform search.");
}
}
If the call to SearchItemsAsync
fails immediately, the ViewModelBase
class’s MessageService
is used to present a dialog to the user.
For more information on the MessageService
, see Chapter 2, “Fundamental Concepts in Windows Phone Development.”
When the search completes, the HandleEbayClientSearchItemsComplete
handler is called. Old requests are ignored. The method returns immediately if the search query does not match the last query (see Listing 27.6).
If the search was not a new search but a request to fetch the next page of the current search results, the results are added to the end of the Items
collection.
void HandleEbayClientSearchItemsComplete(
object sender, SearchItemsCompleteEventArgs args)
{
/* Ignore old query results. */
if (args.Query != lastQuery)
{
return;
}
Busy = false;
if (args.Error == null)
{
if (args.Result.Count > 0)
{
if (appendResult)
{
foreach (var item in args.Result)
{
Items.Add(item);
}
}
else
{
Items = new ObservableCollection<Item>(args.Result);
}
}
else
{
MessageService.ShowMessage("No match found.");
}
}
else
{
MessageService.ShowError(
"An error occured while attempting to search.");
}
}
3.15.14.98