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
/// <summary>
/// Bounce the setting by name if it does not exist, create it and return the default state
/// </summary>
/// <param name="settingName"> </param>
/// <returns> </returns>
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));
}
return 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);
...
The end result should be a treeview that would look something like this
Settings
|
|------ Select Inventory options to hide
| |
| |-- Size [x]
| |-- SKU [x]
| |-- Price [x]
|
|------ Select Supplier options to hide
| |
| |-- Account# [x]
| |-- Phone Number [x]
| |-- Address [x]
I am not sure how I could go about implementing this, and will for the time being probably have to use a less elegant alternative, HOWEVER, I would really like to get something like this working, if anyone has any ideas?
As always any ideas, guidance, or suggestions are greatly appreciated!