SearchBox result suggestion Windows 8.1 - c#

I got a strange issue with my searchBox in Windows 8.1 App.
I got an unhandler exception (and a crush) if in my Suggestion i do not append the querySuggestion and append only the ResultSuggestion.
the problem occurs when i change the queryText.
This is my function
public async void OnSuggest(Windows.UI.Xaml.Controls.SearchBox e, SearchBoxSuggestionsRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
var queryText = args.QueryText != null ? args.QueryText.Trim() : null;
if (string.IsNullOrEmpty(queryText)) return;
TransporterExt tr_search = new TransporterExt();
tr_search.name = queryText;
try
{
var suggestionCollection = args.Request.SearchSuggestionCollection;
ObservableCollection<TransporterExt> querySuggestions = await TransporterService.Search(tr_search);
if (querySuggestions != null && querySuggestions.Count > 0)
{
foreach (TransporterExt tr in querySuggestions)
{
//if (tr.name.ToUpperInvariant().Contains(e.QueryText.ToUpperInvariant()))
//{
// //suggestionCollection.AppendQuerySuggestion(tr.name);
// suggestionCollection.AppendResultSuggestion(tr.name,
// tr.trId.ToString(),
// tr.trId.ToString(),
// imgRef, "imgDesc");
//}
suggestionCollection.AppendQuerySuggestion(tr.name);
}
}
}
catch (Exception)
{
//Ignore any exceptions that occur trying to find search suggestions.
}
deferral.Complete();
}
I got the searchBox inside an UserControl
My controller code
public delegate void SuggestionsRequested(Windows.UI.Xaml.Controls.SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args);
public event Windows.Foundation.TypedEventHandler<Windows.UI.Xaml.Controls.SearchBox, SearchBoxSuggestionsRequestedEventArgs> SearchBoxSuggestionsRequested;
private void SearchBoxSuggestions(Windows.UI.Xaml.Controls.SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{
if (SearchBoxSuggestionsRequested != null)
SearchBoxSuggestionsRequested(sender, args);
}
I got this exception
WinRT: A method was called at an unexpected time.
exception: System.InvalidOperationException - type (string)
Edited Solution - Working function
First of all i remove from the constructor of the page the registration of event
public TruckCrudPage()
{
this.InitializeComponent();
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += navigationHelper_LoadState;
this.navigationHelper.SaveState += navigationHelper_SaveState;
//this.truckForm.SearchBoxSuggestionsRequested += OnSuggest;
}
public async void OnSuggest(Windows.UI.Xaml.Controls.SearchBox e, SearchBoxSuggestionsRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
TransporterExt tr_search = new TransporterExt();
ObservableCollection<TransporterExt> querySuggestions = new ObservableCollection<TransporterExt>();
var queryText = args.QueryText != null ? args.QueryText.Trim() : null;
if (string.IsNullOrEmpty(queryText)) return;
suggested.Clear();
tr_search.name = queryText;
try
{
var suggestionCollection = args.Request.SearchSuggestionCollection;
querySuggestions = await TransporterService.Search(tr_search);
if (querySuggestions != null && querySuggestions.Count > 0 )
{
int i = 0;
foreach (TransporterExt tr in querySuggestions)
{
if (tr.name.StartsWith(e.QueryText, StringComparison.CurrentCultureIgnoreCase))
//if (tr.name.ToLower().Contains(e.QueryText))
{
string name = tr.name;
string detail = tr.trId.ToString();
string tag = i.ToString();
string imageAlternate = "imgDesc";
suggestionCollection.AppendResultSuggestion(name, detail, tag, imgRef, imageAlternate);
suggested.Add(tr);
//Debug.WriteLine("dentro" + suggested.Count);
i++;
}
}
}
}
catch (Exception exc)
{
//Ignore any exceptions that occur trying to find search suggestions.
Debug.WriteLine("Exception generata " + exc.Message);
Debug.WriteLine(exc.StackTrace);
}
deferral.Complete();
}
But it works only with condition StartsWith and i would like to use Contains

You can use SearchBox and SuggestionRequested event to fire the event when type on the SearchBox. I will show an Example
<SearchBox x:Name="SearchBoxSuggestions" SuggestionsRequested="SearchBoxEventsSuggestionsRequested"/>
and write the SearchBoxEventsSuggestionsRequested handler in the code behind
private void SearchBoxEventsSuggestionsRequested(object sender, SearchBoxSuggestionsRequestedEventArgs e)
{
string queryText = e.QueryText;
if (!string.IsNullOrEmpty(queryText))
{
Windows.ApplicationModel.Search.SearchSuggestionCollection suggestionCollection = e.Request.SearchSuggestionCollection;
foreach (string suggestion in SuggestionList)
{
if (suggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
{
suggestionCollection.AppendQuerySuggestion(suggestion);
}
}
}
}
You can add the keyword to SuggestioList, and it will show in the dropdown when you type on the Searchbox.
Create the SuggestionList
public List<string> SuggestionList { get; set; }
initialize the list
SuggestionList = new List<string>();
and add keywords to the list
SuggestionList.Add("suggestion1");
SuggestionList.Add("suggestion2");
SuggestionList.Add("suggestion3");
SuggestionList.Add("suggestion4");
SuggestionList.Add("Fruits");
When you type s on the Searchbox it will show all the keyword starts with s.
Thanks.

Related

How can I pause thread?

Relevant code:
private static Thread m_thread = null;
private static Boolean m_stop = false;
public static Boolean Start(SearcherParams pars)
{
Boolean success = false;
if (m_thread == null)
{
// Perform a reset of all variables,
// to ensure that the state of the searcher is the same on every new start:
ResetVariables();
// Remember the parameters:
m_pars = pars;
// Start searching for FileSystemInfos that match the parameters:
m_thread = new Thread(new ThreadStart(SearchThread));
m_thread.Start();
success = true;
}
return success;
}
private static void SearchThread()
{
Boolean success = true;
String errorMsg = "";
// Search for FileSystemInfos that match the parameters:
if ((m_pars.SearchDir.Length >= 3) && (Directory.Exists(m_pars.SearchDir)))
{
if (m_pars.FileNames.Count > 0)
{
// Convert the string to search for into bytes if necessary:
if (m_pars.ContainingChecked)
{
if (m_pars.ContainingText != "")
{
try
{
m_containingBytes =
m_pars.Encoding.GetBytes(m_pars.ContainingText);
}
catch (Exception)
{
success = false;
errorMsg = "The string\r\n" + m_pars.ContainingText +
"\r\ncannot be converted into bytes.";
}
}
else
{
success = false;
errorMsg = "The string to search for must not be empty.";
}
}
if (success)
{
// Get the directory info for the search directory:
DirectoryInfo dirInfo = null;
try
{
dirInfo = new DirectoryInfo(m_pars.SearchDir);
}
catch (Exception ex)
{
success = false;
errorMsg = ex.Message;
}
if (success)
{
// Search the directory (maybe recursively),
// and raise events if something was found:
SearchDirectory(dirInfo);
}
}
}
else
{
success = false;
errorMsg = "Please enter one or more filenames to search for.";
}
}
else
{
success = false;
errorMsg = "The directory\r\n" + m_pars.SearchDir + "\r\ndoes not exist.";
}
// Remember the thread has ended:
m_thread = null;
// Raise an event:
if (ThreadEnded != null)
{
ThreadEnded(new ThreadEndedEventArgs(success, errorMsg));
}
}
private static void SearchDirectory(DirectoryInfo dirInfo)
{
if (!m_stop)
{
try
{
foreach (String fileName in m_pars.FileNames)
{
FileSystemInfo[] infos = dirInfo.GetFileSystemInfos(fileName);
foreach (FileSystemInfo info in infos)
{
if (m_stop)
{
break;
}
if (MatchesRestrictions(info))
{
// We have found a matching FileSystemInfo,
// so let's raise an event:
if (FoundInfo != null)
{
FoundInfo(new FoundInfoEventArgs(info));
}
}
}
}
if (m_pars.IncludeSubDirsChecked)
{
DirectoryInfo[] subDirInfos = dirInfo.GetDirectories();
foreach (DirectoryInfo subDirInfo in subDirInfos)
{
if (m_stop)
{
break;
}
// Recursion:
SearchDirectory(subDirInfo);
}
}
}
catch (Exception)
{
}
}
}
The stop is working fine I wanted to add also a pause button to pause and resume the thread.
I added a button click event but how do I make the pause/resume actions and where?
This is a link for the complete code : https://pastebin.com/fYYnHBB6
You can use the ManualResetEvent object.
Here is the simplified version.
In your class, create the object:
public static ManualResetEvent _mrsevent = new ManualResetEvent(false);
In your thread function, as part of the loops that search for files/directories:
private static void SearchThread()
{
foreach (String fileName in m_pars.FileNames)
{
_mrsevent.WaitOne();
}
}
From outside the thread you can call:
a) _mrsevent.Set(); // resume the thread.
b) _mrsevent.Reset(); // pause

ContactStore ContactChanged event is not firing when Modifying Contacts

Modified case is never called when modifying the contact or adding a phone number
_contactStore.ContactChanged += _contactStore_ContactChanged;
private void _contactStore_ContactChanged(ContactStore sender, ContactChangedEventArgs args)
{
var defferal = args.GetDeferral();
ContactChangeReader reader = sender.ChangeTracker.GetChangeReader();
IReadOnlyList<ContactChange> changes = reader.ReadBatchAsync().AsTask().Result;
while (changes.Count != 0)
{
foreach (ContactChange change in changes)
{
switch (change.ChangeType)
{
case ContactChangeType.Modified: SomeLogic();
break;
}
}
changes = reader.ReadBatchAsync().AsTask().Result;
}
reader.AcceptChanges();
The problem may be that the ContactStoreAccessType type is incorrect. Please try use AllContactsReadWrite enumeration type.
ContactStore store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadWrite);
store.ContactChanged += Store_ContactChanged;
private void Store_ContactChanged(ContactStore sender, ContactChangedEventArgs args)
{
}

Different behaviors when instantiated from button or timer in c#

I have a function called getMessages that can be called by a Button click (using the RelayCommand trigger) or that is called in a timer every 15s.
The desired behavior is:
webservice > deserialize answer > system notification > updatelistview > insert localDB
But when the function is called by the timer the updatelistview is not done. Why does this happen if the function is the same and works perfectly in the button command?
CODE:
// Get messages for the logged in user
public async void getMessages()
{
try
{
List<FriendGetMessage> msg = new List<FriendGetMessage>();
var response = await CommunicationWebServices.GetCHAT("users/" + au.idUser + "/get", au.token);
if (response.StatusCode == HttpStatusCode.OK) // If there are messages for me.
{
var aux = await response.Content.ReadAsStringAsync();
IEnumerable<FriendGetMessage> result = JsonConvert.DeserializeObject<IEnumerable<FriendGetMessage>>(aux);
if (result != null)
{
foreach (var m in result)
{
msg.Add(m);
}
//MsgList=msg;
foreach (var f in Friends)
{
if (f.msg == null || f.msg.Count() == 0)
{
f.msg = new ObservableCollection<Messages>();
}
foreach (var mess in msg)
{
if (mess.idUser == f.idUser)
{
Messages mm = new Messages();
mm.received = mess.message;
mm.timestamp = "Received " + mess.serverTimestamp;
mm.align = "Right";
// Add to the friend list.
f.msg.Add(mm);
// Add to Local DB
InsertMessage(null, au.idUser.ToString(), f.idUser, mess.message, mess.serverTimestamp);
var notification = new System.Windows.Forms.NotifyIcon()
{
Visible = true,
Icon = System.Drawing.SystemIcons.Information,
BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info,
BalloonTipTitle = "New Message from " + f.name,
BalloonTipText = "Message: " + mess.message,
};
// Display for 5 seconds.
notification.ShowBalloonTip(5);
// The notification should be disposed when you don't need it anymore,
// but doing so will immediately close the balloon if it's visible.
notification.Dispose();
}
}
}
counterChat = 1; // resets the counter
}
}
else {
counterChat = counterChat * 2;
}
//var sql = "select * from chat";
//var respo = GetFromDatabase(sql);
OnPropertyChanged("Friends");
}
catch (Exception e)
{
MessageBox.Show("GetMessages: " + e);
Debug.WriteLine("{0} Exception caught.", e);
}
}
CODE TIMER:
public void chatUpdate()
{
_timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
}
public void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
getMessages();
OnPropertyChanged("Friends");
incChat = 0;
}
}
ADDED - I've also tried this and didn't worked (it seems that is some kind of concurrency problem to the ObservableCollection called Friends (is a friendslist) each friend has an ObservableCollection of messages (is a chat))
public void chatUpdate()
{
_timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
}
public async void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
Application.Current.Dispatcher.Invoke((Action)async delegate { await getMessages(); });
incChat = 0;
}
}
Best regards,
I think you need to make the timer handler be an async method as follows:
public async void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
await getMessages();
OnPropertyChanged("Friends");
incChat = 0;
}
}
This way OnPropertyChanged("Friends") is guaranteed to fire after the work in getMessages is done.
The methods need to change to:
DispatcherTimer _timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
public async void timerchat_Tick(object sender, EventArgs e)
{
//...
await getMessages();
//...
}
public async Task getMessages()
{
try
{
// ... your code here
string result = await response.Content.ReadAsStringAsync();
// .... rest of your code
}
catch (Exception e)
{
MessageBox.Show("GetMessages: " + e);
}
}
It is solved. The problem was in my ViewModels I was opening multiple threads and sometimes the right one would update the UI and sometimes no.
Thanks for all the answers.

SearchBox windows App 8.1 , searching a substring "contained"

Building an App for windows store 8.1, i implement my searchbox, following the tutorial.
But, it works good only searching a substring that "startWith" another.
If i try to use something like "contains" i got a crush, an unhandled exception.
It works at the first, but if i change the query in the searchBox it crush ... often, not allways.
I can't understand the debugger message,because it refers to the app code...
That's my debugger message
Debugger:Debugger Break
A break in the debugger session because a user paused the session.
Time: 13/04/2014 12:34:34
Thread:<No Name>[6220]
and refers to
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
}
my e object got an Exception : incorrect Parameter, handled : false....
that's my SuggestionRequested function, where there is the problem (i think)
public async void OnSuggest(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
TransporterExt tr_search = new TransporterExt();
ObservableCollection<TransporterExt> querySuggestions = new ObservableCollection<TransporterExt>();
var queryText = args.QueryText != null ? args.QueryText.Trim() : null;
if (string.IsNullOrEmpty(queryText)) return;
suggested.Clear();
tr_search.name = queryText;
try
{
var suggestionCollection = args.Request.SearchSuggestionCollection;
querySuggestions = await TransporterService.Search(tr_search);
if (querySuggestions != null && querySuggestions.Count > 0 )
{
int i = 0;
foreach (TransporterExt tr in querySuggestions)
{
string strB = sender.QueryText;
string strA = tr.name;
if(await Utility.Compare(strA,strB))
//using this condition all works fine
//if (tr.name.StartsWith(sender.QueryText, StringComparison.CurrentCultureIgnoreCase))
{
string name = tr.name;
string detail = tr.trId.ToString();
string tag = i.ToString();
string imageAlternate = "imgDesc";
suggestionCollection.AppendResultSuggestion(name, detail, tag, imgRef, imageAlternate);
if(tr!=null)
suggested.Add(tr);
i++;
}
}
}
}
catch (Exception exc)
{
//Ignore any exceptions that occur trying to find search suggestions.
Debug.WriteLine("Exception " + exc.Message);
Debug.WriteLine(exc.StackTrace);
}
deferral.Complete();
}
and the Contains utility
public static async Task<bool>Compare(string A, string B) {
bool contains = Regex.Match(A, B, RegexOptions.IgnoreCase).Success;
Debug.WriteLine("regex ="+contains);
return contains;
}
I got this SearchBox in a UserControl, and that's the code of my UC
public delegate void SuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args);
public event Windows.Foundation.TypedEventHandler<SearchBox, SearchBoxSuggestionsRequestedEventArgs> SearchBoxSuggestionsRequested;
private void SearchBoxSuggestions(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{
if (SearchBoxSuggestionsRequested != null)
SearchBoxSuggestionsRequested(sender, args);
else
Debug.WriteLine("TruckFormUCException");
}
It's possible to search with another logic instead of "startswith"?... where's my fault?

Skydrive wp7 App: GetAsync method stopped working

On my windows phone 7 Mango app I use the Microsoft.Live and Microsoft.Live.Controls references to download and upload on Skydrive. Logging in and uploading files works fine but whenever I call the "client.GetAsync("/me/skydrive/files");" on the LiveConnectClient the Callback result is empty just containing the error: "An error occurred while retrieving the resource. Try again later."
I try to retrieve the list of files with this method.
This error suddenly occured without any change on the source code of the app (I think..) which worked perfectly fine for quite a while until recently. At least I didn't change the code section for up- or downloading.
I tried out the "two-step verification" of Skydrive, still the same: can log in but not download.
Also updating the Live refercences to 5.5 didn't change anything.
Here is the code I use. The error occurs in the "getDir_Callback" in the "e" variable.
Scopes (wl.skydrive wl.skydrive_update) and clientId are specified in the SignInButton which triggers "btnSignin_SessionChanged".
private void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
connected = true;
processing = true;
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(UploadCompleted);
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompleted);
client.DownloadProgressChanged += new EventHandler<LiveDownloadProgressChangedEventArgs>(client_DownloadProgressChanged);
infoTextBlock.Text = "Signed in. Retrieving file IDs...";
client.GetAsync("me");
}
else
{
connected = false;
infoTextBlock.Text = "Not signed into Skydrive.";
client = null;
}
}
private void OnGetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
if (e.Error == null)
{
client.GetCompleted -= new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.GetCompleted += getDir_Callback;
client.GetAsync("/me/skydrive/files");
client_id = (string)e.Result["id"];
if (e.Result.ContainsKey("first_name") && e.Result.ContainsKey("last_name"))
{
if (e.Result["first_name"] != null && e.Result["last_name"] != null)
{
infoTextBlock.Text = "Hello, " +
e.Result["first_name"].ToString() + " " +
e.Result["last_name"].ToString() + "!";
}
}
else
{
infoTextBlock.Text = "Hello, signed-in user!";
}
}
else
{
infoTextBlock.Text = "Error calling API: " +
e.Error.ToString();
}
processing = false;
}
public void getDir_Callback(object s, LiveOperationCompletedEventArgs e)
{
client.GetCompleted -= getDir_Callback;
//filling Dictionary with IDs of every file on SkyDrive
if (e.Result != null)
ParseDir(e);
if (!String.IsNullOrEmpty(e.Error.Message))
infoTextBlock.Text = e.Error.Message;
else
infoTextBlock.Text = "File-IDs loaded";
}
Yo shall use client.GetAsync("me/SkyDrive/files", null) in place of client.GetAsync("me");
This is my code and it works fine.
private void btnSignIn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
try
{
if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_GetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_UploadCompleted);
client.GetAsync("me/SkyDrive/files", null);
client.DownloadAsync("me/SkyDrive", null);
canUpload = true;
ls = e.Session;
}
else
{
if (client != null)
{
MessageBox.Show("Signed out successfully!");
client.GetCompleted -= client_GetCompleted;
client.UploadCompleted -= client_UploadCompleted;
canUpload = false;
}
else
{
canUpload = false;
}
client = null;
canUpload = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void client_GetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
try
{
List<System.Object> listItems = new List<object>();
if (e.Result != null)
{
listItems = e.Result["data"] as List<object>;
for (int x = 0; x < listItems.Count(); x++)
{
Dictionary<string, object> file1 = listItems[x] as Dictionary<string, object>;
string fileName = file1["name"].ToString();
if (fileName == lstmeasu[0].Title)
{
folderID = file1["id"].ToString();
folderAlredyPresent = true;
}
}
}
}
catch (Exception)
{
MessageBox.Show("An error occured in getting skydrive folders, please try again later.");
}
}
It miraculously works again without me changing any code. It seems to be resolved on the other end. I have no clue what was wrong.

Categories

Resources