Okay, I am trying to set up a settings page for my app. On this page I
want the user to select a series of options for what fields to display
on another page.
I have a settings system overloaded using the using Xamarin.Essentials;
extensions, so I can handle lookup, generation, and clearing of various
settings. I will then later in the target page use these functions to
alter various IsVisible
options.
When a switch is toggled (or eve checkbox checked unchecked) I want the StateChanged
event to fire and run my custom callback using the dynamic data from
the event to modify the internal stored settings for the app.
I am thinking that it should go something like this...
This is a dataclass to store a group of settings to be passed to the treeview.
public class SettingsOption : EventParent, INotifyPropertyChanged { /// <summary> /// private storage Displayname /// </summary> private string displayname; /// <summary> /// private storage ImageIcon /// </summary> private ImageSource imageIcon; /// <summary> /// private storage PropertiesGroup /// </summary> private ObservableCollection<SettingsOption> propertiesGroup; /// <summary> /// private storage PropertyName /// </summary> private string propertyName; /// <summary> /// Gets or sets the value for Displayname /// </summary> public string Displayname { get => displayname; set { SetProperty(ref displayname, value, nameof(Displayname)); OnPropertyChanged(nameof(Displayname)); } } /// <summary> /// Gets or sets the value for ImageIcon /// </summary> public ImageSource ImageIcon { get => imageIcon; set { SetProperty(ref imageIcon, value, nameof(ImageIcon)); OnPropertyChanged(nameof(ImageIcon)); } } /// <summary> /// Gets or sets the value for PropertiesGroup /// </summary> public ObservableCollection<SettingsOption> PropertiesGroup { get => propertiesGroup; set { SetProperty(ref propertiesGroup, value, nameof(PropertiesGroup)); OnPropertyChanged(nameof(PropertiesGroup)); } } /// <summary> /// Gets or sets the value for PropertyName /// </summary> public string PropertyName { get => propertyName; set { SetProperty(ref propertyName, value, nameof(PropertyName)); OnPropertyChanged(nameof(PropertyName)); } } /// <summary> /// Defines the PropertyChanged /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// The RaisedOnPropertyChanged /// </summary> /// <param name="_PropertyName"> The _PropertyName <see cref="string" /> </param> public void RaisedOnPropertyChanged(string _PropertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(_PropertyName)); } }
This is a function I created in order to make a lookup and toggle of the setting possible
private bool BounceSetting(string settingName) { if (!AppSettingsFunctions.CheckKey(settingName)) { AppSettingsFunctions.SaveSettingData(settingName, true); } else { //Save the new setting as a process of the inverse of getting the existing data AppSettingsFunctions.SaveSettingData(settingName, !AppSettingsFunctions.GetBoolSetting(settingName)); } }
I want to then be able to setup the treeview like this.
private void BuildSettingsTreegroups() { tvSettingsOptions.ChildPropertyName = "PropertiesGroup"; tvSettingsOptions.ItemTemplateContextType = ItemTemplateContextType.Node; tvSettingsOptions.IsAnimationEnabled = true; tvSettingsOptions.Indentation = 20; tvSettingsOptions.AutoExpandMode = Syncfusion.TreeView.Engine.AutoExpandMode.RootNodesExpanded; tvSettingsOptions.ItemsSource = SettingsGroup; tvSettingsOptions.ItemTemplate = new DataTemplate(() => {
var displayName = new Label { VerticalTextAlignment = TextAlignment.Center }; var slEntry = new StackLayout { Orientation = StackOrientation.Horizontal }; var optionIcon = new Image { HeightRequest = 26, WidthRequest = 26 }; var swSetting = new SfSwitch(); optionIcon.SetBinding(Image.SourceProperty, new Binding("Content.ImageIcon")); displayName.SetBinding(Label.TextProperty, new Binding("Content.Displayname")); swSetting.SetBinding(SfSwitch.IsOnProperty, AppSettingsFunction.GetBoolSetting("Content.PropertyName")); swSetting.StateChanged += (s, e) => BounceSetting("Content.PropertyName"); slEntry.Children.Add(optionIcon); slEntry.Children.Add(displayName); slEntry.Children.Add(swSetting); return slEntry; });
}
The problem is that the swSetting
binding. To get the current setting the app needs to call the settings function I overloaded in my AppSettingsFunction
class.
With the above code I could theoretically build my settings page like this then building an ObservableCollection<SettingsOptions>
object that I populate my settings into like this ...
var mainOptionsgroup = new SettingsOption(); var inventoryOptions = new SettingsOption();
inventoryOptions.Displayname = "Select Inventory options to hide"; inventoryOptions.ImageIcon = "InventoryIcon"; inventoryOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "Size", PropertyName = "inv_ShowSize" }); inventoryOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "SKU", PropertyName = "inv_SKU" }); inventoryOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "Price", PropertyName = "inv_Price" }); var supplierPageOptions = new SettingsOption(); supplierPageOptions.Displayname = "Select Supplier options to hide"; supplierPageOptions.ImageIcon = "Suppliers"; supplierPageOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "Account#", PropertyName = "sup_Account" }); supplierPageOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "Phone Number", PropertyName = "sup_Phone" }); supplierPageOptions.PropertiesGroup.Add(new SettingsOption { Displayname = "Address", PropertyName = "sup_Address" });
mainOptionsgroup.Displayname = "Settings"; mainOptionsgroup.PropertiesGroup.Add(inventoryOptions); mainOptionsgroup.PropertiesGroup.Add(supplierPageOptions);
Any ideas would be most appreciated!
Thanks!
Here is what I had to do to make this work
For the ItemsTemplate I simply made the sfSwitch
use it's AutomationIdProperty
hold the value of the property, then look it up using the lambda for calling BounceSetting(((SfSwitch)s).AutomationId);
..
I added a Property to my SettingsOption
class for LastState so that I can lookup the existing value and send it in the data.
tvSettingsOptions.ItemTemplate = new DataTemplate(() =>
{
try
{
var slEntry = new StackLayout { Orientation = StackOrientation.Horizontal };
var optionIcon = new Image { HeightRequest = 26, WidthRequest = 26 };
var displayName = new Label { VerticalTextAlignment = TextAlignment.Center };
var swSetting = new SfSwitch();
optionIcon.SetBinding(Image.SourceProperty, new Binding("Content.ImageIcon"));
displayName.SetBinding(Label.TextProperty, new Binding("Content.Displayname"));
swSetting.SetBinding(SfSwitch.AutomationIdProperty, new Binding("Content.PropertyName"));
swSetting.SetBinding(SfSwitch.IsOnProperty, new Binding("Content.LastState"));
swSetting.StateChanged += (s, e) => BounceSetting(((SfSwitch)s).AutomationId);
slEntry.Children.Add(optionIcon);
slEntry.Children.Add(displayName);
slEntry.Children.Add(swSetting);
var grid = new Grid();
grid.Children.Add(slEntry);
return grid;
}
catch (Exception ex)
{
Debug.WriteLine($"SettingsPage.xaml.cs->BuildSettingsTreegroups()->{ex.StackTrace}->{ex.Message}.{Environment.NewLine}{ex.InnerException}.{Environment.NewLine}{ex.Data}");
return new Label { Text = "ERROR" };
}
});
Thanks anyhow!