Getting data from the observable collection to the button event - xamarin

public ObservableCollection<WordList> MyWordList { get; set; }
public DictionaryPage()
{
InitializeComponent();
BindingContext = new DictionaryPageViewModel();
MyWordList = new ObservableCollection<WordList>
{
new WordList { Color = "Red", Letter = "A", Word = "Abdomen", Meaning = "Mean : " + "Mean",Detail= "Mean", Voice = "myVoice.mp3" }
};
}
private async void PronunciationButton_Clicked(object sender, System.EventArgs e)
{
await CrossMediaManager.Current.PlayFromAssembly("HERE HERE HERE");
}
I have an observable collection like this and I want to put the voice value in it to the button event below. Thanks for your help

MyWordList is a class level variable. Just reference it in your Clicked handler
private async void PronunciationButton_Clicked(object sender, System.EventArgs e)
{
For each (var word in MyWordList) {
await CrossMediaManager.Current.PlayFromAssembly(word.Voice);
}
}

Related

How to transfer data from one page to another xamarin

I have three pages, I enter the data on the second page and transfer it to page number one, returning to it at the same time, there is no problem with this, I use navigation, like this:
private async void OnSaveTitleButtonCliked(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
var mainpage = new MainPage();
mainpage.BindingContext = title_data;
await Navigation.PushAsync(mainpage);
}
But I also need to transfer this data to page number three, so that I can go there from the first page and see, I tried the mvvm, but so far I have not understood how it works.
Please tell me how to do it better:)
Pass data by constructor:
In Page1:
private async void GoToPage2(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
//Pass the model here
var Page2 = new Page2(title_data);
await Navigation.PushAsync(Page2);
}
In Page2:
public partial class Page2 : ContentPage
{
public LabelViewModel model;
public Page2(LabelViewModel m) {
InitializeComponent();
this.model = m;
//You can use your model here
}
}
Pass data by public property:
In Page1:
private async void GoToPage2(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
var Page2 = new Page2();
//Pass the model here
Page2.model = title_data;
await Navigation.PushAsync(Page2);
}
In Page2:
public partial class Page2 : ContentPage
{
public LabelViewModel model;
public Page2()
{
InitializeComponent();
//You can use your model here
Console.WriteLine(model.Label);
Console.WriteLine(model.Date);
}
}
Let me know if you have any questions.
I'll let some examples here
On the first page (who calls the second one)
private async void MenuLista(object sender, EventArgs e)
{
var item = (ModelosPPP)((Button)sender).BindingContext;
if (PopupRunnning != false)
return;
var page = new MenuListSV(item);
PopupRunnning = true;
page.Action += async (a, b) =>
{
switch (b)
{
case 1:
await DisplayAlert("PDF", null, "ok");
break;
case 2:
await DisplayAlert("Reenviar", null, "ok");
break;
case 3:
await DisplayAlert("Excluir", null, "ok");
break;
}
};
page.Disappearing += (c, d) =>
{
PopupRunnning = false;
};
await PopupNavigation.Instance.PushAsync(page);
}
in Second Page
public partial class MenuListSV : PopupPage
{
public MenuListSV(Models.ModelosPPP obj)
{
InitializeComponent();
BindingContext = obj;
}
public EventHandler<int> Action;
public async void MenuChoice(object sender, EventArgs e)
{
var btn = sender as Button;
switch (btn.Text)
{
case "Abrir PDF":
Action?.Invoke(this, 1);
break;
case "Reenviar":
Action?.Invoke(this, 2);
break;
case "Excluir":
Action?.Invoke(this, 3);
break;
}
await PopupNavigation.Instance.PopAsync();
}
}

Xamarin Forms MessagingCenter Subscribe called two times

I'm clicking on a product item in listview in product page viewmodel to show a popup(using rg.plugin popup) for selecting one of the product variants.After selecting variant,i am sending the selected variant to product page using messagingcenter from variant popup page viewmodel,subscribed in product page viewmodel constructor. working fine there.when i navigate to the previous page and then came back to this product page for adding one or more variant to the
same previously selected product,Messagingcenter subscribe called twice and product value increased twice.Tried to subscribe in the product page onappearing and unsubscribe in disappearing method.still calling two times? How to solve this issue?
calling popup:
var result = await dataService.Get_product_variant(store_id, product_id);
if (result.status == "success")
{
ind_vis = false;
OnPropertyChanged("ind_vis");
App.Current.Properties["product_variant_result"] = result;
App.Current.Properties["cartitems"] = purchaselist;
App.Current.Properties["selected_product"] = product_List2 ;
await PopupNavigation.Instance.PushAsync(new Popup_variant());
}
popup viewmodel: sending message
public Popup_variant_vm()
{
Radio_btn = new Command<Product_variant_list2>(Radio_stk_tapped);
product_variant_list = new List<Product_variant_list2>();
purchaselist = new ObservableCollection<Product_list2>();
show_variants();
}
internal void Confirm_variant()
{
if(App.Current.Properties.ContainsKey("selected_variant"))
{
MessagingCenter.Send<Popup_variant_vm, object>(this, "selected_variant", App.Current.Properties["selected_variant"]); //Message send from popup to product page
}
else
{
DependencyService.Get<IToast>().LongAlert("Please select any size");
}
}
product page viewmodel: subscribed here..called twice when navigating from previous page to this
public Store_page()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
var vm = new store_page_vm();
vm.Navigation = Navigation;
BindingContext = vm;
MessagingCenter.Unsubscribe<Popup_variant_vm, object>(this, "selected_variant");
MessagingCenter.Subscribe<Popup_variant_vm, object>(this, "selected_variant",async (sender, selected_variant) =>
{
var vm1 = BindingContext as store_page_vm;
vm1?.Addcart2(selected_variant);// called twice
});
}
unsubscribed in product cs page
protected override void OnDisappearing()
{
var vm = BindingContext as store_page_vm;
vm?.Save_cart();
MessagingCenter.Unsubscribe<Popup_variant_vm>(this, "selected_variant");
}
Your unsubscription should look something like below and it should work :
MessagingCenter.Unsubscribe<Popup_variant_vm, object>(this, "selected_variant");
https://stackoverflow.com/a/44753021/10937160
try this, and make sure you do not call Subscribe more than once.
My solution:
put unsubscribe sentence into subscribe body !!
MessagingCenter.Subscribe<object, string>(this, "IdSearch", (sender, arg) =>
{
listView.ItemsSource = arg;
MessagingCenter.Unsubscribe<object, string>(this, "IdSearch");
}, BindingContext);
I have created static counter variable in my app the in subscriber I have done this:
public static class Constants
{
public static int msgCenterSubscribeCounter { get; set; } = 0;
}
MessagingCenter.Subscribe<object, string>(this, "hello", (sender, arg) =>
{
Constants.msgCenterSubscribeCounter++;
if (arg.Equals("hello") && Constants.msgCenterSubscribeCounter == 1)
{
// handle your logic here
}
});
Reset counter in OnDisappearing() method from where you have called Send.
Changing Messagingcenter in to single subscription.
public class Messagingcenter_singleton
{
private static Messagingcenter_singleton _instance;
private bool isActivated = false;
private Action<string> callBackFun = null;
public static Messagingcenter_singleton Instance()
{
if (_instance == null)
{
_instance = new Messagingcenter_singleton();
}
return _instance;
}
public void setCallBack(Action<string> eventCallBack)
{
callBackFun = eventCallBack;
}
public void startSubscribe()
{
if (!isActivated)
{
isActivated = true;
MessagingCenter.Subscribe<string, string>(this, "Name", eventCallBack);
}
}
private void eventCallBack(string arg1, string arg2)
{
if (callBackFun != null)
{
InvokeMethod(new Action<string>(callBackFun), arg2);
}
}
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
}
Use Below Code in you view model class
public void initSubscribe()
{
Messagingcenter_singleton.Instance().startSubscribe();
Messagingcenter_singleton.Instance().setCallBack(eventCallBack)
}
public void eventCallBack(string arg2)
{
// write your code here
}

Exception of type 'System.Collections.Generic.KeyNotFoundException' was thrown ? in Xamarin.Forms

i wanna use simple database in Xamarin Forms. So i used this code;
public partial class DBExample : ContentPage
{
string _dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),"myDB.db3");
public DBExample ()
{
InitializeComponent ();
}
private async void InsertButton(object sender, EventArgs e)
{
SQLiteConnection db=null;
try
{
db = new SQLiteConnection(_dbPath);
}
catch (Exception ex)
{
await DisplayAlert(null, ex.Message, "OK");
}
db.CreateTable<Users>();
var maxPk = db.Table<Users>().OrderByDescending(c => c.Id).FirstOrDefault();
Users users = new Users()
{
Id = (maxPk == null ? 1 : maxPk.Id + 1),
Name = userName.Text
};
db.Insert(users);
await DisplayAlert(null,userName.Text + "saved","OK");
await Navigation.PopAsync();
}
}
and i have problem. You can see it in Headtitle.
"Exception of type 'System.Collections.Generic.KeyNotFoundException' was thrown"
im waiting your support. Thanks for feedback.

getting slower performance in textBox1_TextChanged in windows phone

I have a search text-box in my app. In my database there are two column named English and Bangla. I can search either Bangla or English. there is a button beside search text-box.By default English search is activated. I can change the search option by clicking the button. It works correctly but problem is that the search is very slow.
search option selection code by clicking button is:
private void button5_Click(object sender, RoutedEventArgs e)
{
if (SearchMood % 2 != 0)
{
//search bangla column from the database
button5.Content = "Eng";
}
else {
//search english column from the database
button5.Content = "Bng";
}
SearchMood++;
}
Code for searching is:
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
List<dataLists> mylist = new List<dataLists>();
string word = textBox1.Text;
try
{
if (SearchMood % 2 == 0)// for english search
{
// show 5 words in listbox matched with entered text
var contacts = (from m in db.Dics where m.English.StartsWith(word) select new { m.English, m.Bangla }).Take(5);
string s1, s2;
try
{
foreach (var a in contacts)
{
s1 = a.English;
s2 = a.Bangla;
mylist.Add(new dataLists() { Eng = s1, Bng = s2 });
}
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
listBox1.ItemsSource = mylist;
}
else // for bangla search
{
// show 5 words in listbox matched with entered text
var contacts = (from m in db.Dics where m.Bangla.StartsWith(word) select new { m.English, m.Bangla }).Take(5);
string s1, s2;
try
{
foreach (var a in contacts)
{
s1 = a.English;
s2 = a.Bangla;
mylist.Add(new dataLists() { Eng = s1, Bng = s2 });
}
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
listBox1.ItemsSource = mylist;
}
}
catch { }
}
How can I increase the performance of searching??? Can anyone give any solution|???
N:B: My table creation script looks like
public System.Data.Linq.Table<Dic> Dics
{
get
{
return this.GetTable<Dic>();
}
}
public System.Data.Linq.Table<Learn_table> Learn_tables
{
get
{
return this.GetTable<Learn_table>();
}
}
}
[global::System.Data.Linq.Mapping.TableAttribute(Name="dic")]
public partial class Dic : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _Serial;
private string _English;
private string _Bangla;
private System.Nullable<int> _Fav;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnSerialChanging(int value);
partial void OnSerialChanged();
partial void OnEnglishChanging(string value);
partial void OnEnglishChanged();
partial void OnBanglaChanging(string value);
partial void OnBanglaChanged();
partial void OnFavChanging(System.Nullable<int> value);
partial void OnFavChanged();
#endregion
public Dic()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="serial", Storage="_Serial", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int Serial
{
get
{
return this._Serial;
}
set
{
if ((this._Serial != value))
{
this.OnSerialChanging(value);
this.SendPropertyChanging();
this._Serial = value;
this.SendPropertyChanged("Serial");
this.OnSerialChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="english", Storage="_English", DbType="NVarChar(2000)")]
public string English
{
get
{
return this._English;
}
set
{
if ((this._English != value))
{
this.OnEnglishChanging(value);
this.SendPropertyChanging();
this._English = value;
this.SendPropertyChanged("English");
this.OnEnglishChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="bangla", Storage="_Bangla", DbType="NVarChar(2000)")]
public string Bangla
{
get
{
return this._Bangla;
}
set
{
if ((this._Bangla != value))
{
this.OnBanglaChanging(value);
this.SendPropertyChanging();
this._Bangla = value;
this.SendPropertyChanged("Bangla");
this.OnBanglaChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="fav", Storage="_Fav", DbType="Int")]
public System.Nullable<int> Fav
{
get
{
return this._Fav;
}
set
{
if ((this._Fav != value))
{
this.OnFavChanging(value);
this.SendPropertyChanging();
this._Fav = value;
this.SendPropertyChanged("Fav");
this.OnFavChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Your problem appears in using TextChanged event Handler. Place a breakpoint there and you will see it firing twice and hence causing the slow performance for you. It seems a bug in WP7 TextBox control.
Use KeyUp event handler, instead of textBox1_TextChanged
void textBox1_KeyUp(object sender, KeyEventArgs e)
{
//your code
}
Hope this solves your problem. !!
You can use of AutoCompleteBox rather than use of TextBox. AutoCompleteBox available in Microsoft.Phone.Control.Toolkit.
Execute you select query at once when you select language on buttonClick and assign result of your query to AutoCompleteBox.Itemsource. It should really increase search performance.
<toolkit:AutoCompleteBox x:Name="AutoBoxFood" Width="440" SelectionChanged="txtFodd_SelectionChanged" FilterMode="StartsWith" HorizontalAlignment="Left" Height="70"/>
Add indexes to the columns in the database file.

How to pass parameters to a method by reflection

Further to my precedent question, I want to pass parameters to the method "WriteTrace". But I don't know how to do this.
Here the actual code :
public class Trace
{
public void WriteTrace(object sender, EventArgs e)
{
Console.WriteLine("Trace !");
}
}
public void SubscribeEvent(Control control)
{
if (typeof(Control).IsAssignableFrom(control.GetType()))
{
Trace test = this;
MethodInfo method = typeof(Trace).GetMethod("WriteTrace");
EventInfo eventInfo = control.GetType().GetEvent("Load");
// Create the delegate on the test class because that's where the
// method is. This corresponds with `new EventHandler(test.WriteTrace)`.
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, test, method);
// Assign the eventhandler. This corresponds with `control.Load += ...`.
eventInfo.AddEventHandler(control, handler);
}
}
Now I want to get some infos in the trace :
The name of the control
The name of the event
public void WriteTrace(object sender, EventArgs e)
{
Console.WriteLine("Control : " + e.ControlName + "Event : " + e.EventName);
}
Do I create a class TraceEventArgs which derives from EventArgs with these infos ?
How to pass these infos in the method SubscribeEvent ?
Thanks for your help,
Florian
EDIT
Sorry, here now the reference to "my previous question" : Subscribe to an event with Reflection
Try something like this:
public void WriteTrace(object sender, EventArgs e, string eventName)
{
Control c = (Control)sender;
Console.WriteLine("Control: " + f.Name + ", Event: " + eventName);
}
public void SubscribeEvent(Control control, string eventName) {
EventInfo eInfo = control.GetType().GetEvent(eventName);
if (eInfo != null) {
// create a dummy, using a closure to capture the eventName parameter
// this is to make use of the C# closure mechanism
EventHandler dummyDelegate = (s, e) => WriteTrace(s, e, eventName);
// Delegate.Method returns the MethodInfo for the delegated method
Delegate realDelegate = Delegate.CreateDelegate(eInfo.EventHandlerType, dummyDelegate.Target, dummyDelegate.Method);
eInfo.AddEventHandler(control, realDelegate);
}
}

Resources