using System;
using System.Collections.Generic;
using System.ComponentModel;
using Unity.Properties;
using UnityEngine;
using UnityEngine.Serialization;
///
/// Represents a data model that can be used to power the UI by binding its properties
/// to visual elements. Provides functionality to notify subscribers of property value changes.
///
public class MyInventoryDataModel : INotifyPropertyChanged
{
// This is the data model that will be used to power the UI
private readonly List _masterItemList;
// Each visual element in the tutorial has its own #region defined
#region TextField Example
// It is considered best practice to use the public param as the property with a getter and setter
// so that you can perform other functions such as validation and raising the PropertyChanged event
///
/// Represents the public property for accessing or modifying the text content encapsulated by the data model.
/// Changes to this property trigger notifications to inform subscribers of updates, enabling UI bindings
/// or other reactionary mechanisms to reflect the altered state of the data.
///
[CreateProperty] // Use the CreateProperty attribute to mark this field as bindable
public string FilterText
{
// Get just returns the value
get
{
return _filterText;
}
// Set saves the new value and raises an event to alert subscribers of the change
set
{
if (_filterText != value)
{
_filterText = value;
// Filter the results based on the new text
FilterByFilterText(value);
OnPropertyChanged(nameof(FilterText));
}
}
}
///
/// Stores the raw text content for the data model. This private field holds the text value
/// and acts as the backing field for the public property. The value
/// changes can be observed via the property change notification mechanism to support UI updates
/// or other reactive programming patterns.
///
[DontCreateProperty] // Use the DontCreateProperty attribute on the private var to keep it isolated
private string _filterText;
#endregion
#region DropdownField Example
///
/// Represents the currently selected option in a collection of choices.
/// This property supports data binding and notifies subscribers of value changes, enabling dynamic updates
/// to the associated UI elements or other dependent components.
///
[CreateProperty]
public string SelectedItemType
{
get => _selectedItemType;
set
{
if (_selectedItemType != value)
{
_selectedItemType = value;
FilterByItemType();
OnPropertyChanged(nameof(SelectedItemType));
}
}
}
///
/// Stores the underlying value for the selected option in the data model.
/// This private backing field is accessed and modified via the public property 'SelectedItemType',
/// which handles validation, notification of changes, and other associated logic.
///
[DontCreateProperty]
private string _selectedItemType;
///
/// Represents the public property for managing a collection of selectable options within the data model.
/// Changes to this property notify subscribers, facilitating dynamic UI updates or other mechanisms
/// relying on the modification and reflection of available options.
///
[CreateProperty]
public List ItemTypes
{
get => _itemTypes;
set
{
if (_itemTypes != value)
{
_itemTypes = value;
OnPropertyChanged(nameof(ItemTypes));
}
}
}
///
/// Defines the private backing field for storing a list of options managed within the data model.
/// Interactions with this field are typically mediated through its corresponding public property
/// to ensure proper encapsulation, event triggering, or validation logic.
///
[DontCreateProperty]
private List _itemTypes = new List();
#endregion
#region Listview Example
///
/// Represents a collection of items within the data model, allowing for retrieval or modification
/// of the list. Changes to this property notify subscribers of updates, enabling dynamic UI bindings
/// or other mechanisms to respond to the modified collection data.
///
[CreateProperty]
public List Items
{
get => _items;
set
{
if (_items != value)
{
_items = value;
OnPropertyChanged(nameof(Items));
}
}
}
///
/// Represents a collection of strings that can be accessed or modified.
/// Changes to this collection notify subscribers, facilitating updates to UIs or other dependent systems.
///
[DontCreateProperty]
private List _items = new List();
#endregion
#region Event Example
///
/// Represents an unbindable property that, when set to true, triggers the invocation of the form reset process.
/// It is used to signal the need for resetting the state of the form and does not provide
/// a backing store for persistent data. Setting this property performs the reset operation directly
/// and offers a simple way to capture a button event in the UI.
///
public bool RaiseResetFormEvent
{
set
{
if (value)
{
ResetForm();
}
}
}
///
/// Represents the message associated with an event, which can be dynamically updated
/// and notifies subscribers about its changes. Typically used to display or log event-related
/// information, supporting reactive UI updates or behavior when modified.
///
[CreateProperty]
public string EventMessage
{
get => _eventMessage;
set
{
if (_eventMessage != value)
{
_eventMessage = value;
OnPropertyChanged(nameof(EventMessage));
}
}
}
///
/// Represents the event message associated with the data model. This property is typically utilized
/// to provide feedback or display status messages resulting from user interaction or internal logic.
/// Changes to this property trigger notification events to update any observers or bound UI elements.
///
[DontCreateProperty]
private string _eventMessage = "Reset";
#endregion
#region CustomDataBinding Example
///
/// Represents the property for accessing or modifying the currently selected item
/// in a collection. Changing this property's value triggers the notification mechanism
/// to inform subscribers of the update, enabling responsive actions such as updating
/// the user interface or performing related operations.
///
[CreateProperty]
public ItemData SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
}
}
}
///
/// Represents the currently selected item from a collection of available items within the data model.
/// Assigning a new value to this property triggers a notification to inform subscribers of the change,
/// enabling UI updates or other actions dependent on the selected item's state.
///
[DontCreateProperty]
private ItemData _selectedItem;
#endregion
///
/// Represents a data model that implements the INotifyPropertyChanged interface to provide
/// notifications when properties of the model change. This class is designed to handle and manage
/// data, including initialization and loading of values, which can then be observed by subscribers.
///
public MyInventoryDataModel()
{
// Initialize the data model with some default values
// In an actual project, this is where you would load your data from whatever source you are using
// For this tutorial we will load some static data from a JSON array
_masterItemList = new List();
LoadSimulatedData();
}
///
/// Filters the `Items` list based on the currently selected item type.
/// If the selected item type is `AllItems`, all items are included.
/// Otherwise, only items matching the selected type are retained in the list.
///
private void FilterByItemType()
{
// Filter the results based on the selected option
if (SelectedItemType == nameof(ItemType.AllItems))
{
Items = new List(_masterItemList);
}
else
{
Items = new List(_masterItemList);
Items.RemoveAll(item => item.type != (ItemType)Enum.Parse(typeof(ItemType), SelectedItemType));
}
}
///
/// Filters the items in the collection based on the provided filter text. The method updates the
/// `Items` property to contain only those items that match the specified criteria in their
/// name, description, or value.
///
/// The text used to filter items. Items are retained if their
/// name, description, or value contains this text, ignoring case.
private void FilterByFilterText(string filterText)
{
// If the filter text is empty, reset the list to the full list
if (string.IsNullOrEmpty(filterText))
{
Items = new List(_masterItemList);
return;
}
// Filter the list by the filter text, look in name OR description OR value converted to int
Items = new List(_masterItemList);
// First filter to the type
FilterByItemType();
// Then filter by the text
Items.RemoveAll(item => item.name.ToLower().IndexOf(filterText.ToLower(), StringComparison.Ordinal) == -1 &&
item.description.ToLower().IndexOf(filterText.ToLower(), StringComparison.Ordinal) == -1 &&
item.value.ToString().ToLower().IndexOf(filterText.ToLower(), StringComparison.Ordinal) == -1);
}
// This is the event raised when a property changes
public event PropertyChangedEventHandler PropertyChanged;
///
/// Notifies subscribers that a property value has changed. This method is commonly used
/// within property setters to trigger UI updates or other responses in code that observes
/// property change events.
///
/// The name of the property whose value has changed. Typically passed as the name of the calling property.
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
///
/// Resets the form by clearing the filter text, setting the selected item type to "AllItems",
/// deselecting any selected item, and updating the event message to indicate the form has been reset.
/// This method is typically invoked when a user action or event requires the UI form to be cleared
/// and restored to its default state.
///
private void ResetForm()
{
FilterText = "";
SelectedItemType = nameof(ItemType.AllItems);
SelectedItem = null;
EventMessage = "Form Reset";
}
///
/// Populates the data model with simulated data for testing or demonstration purposes.
/// This method initializes various properties with predefined values to simulate
/// the structure and content of the data typically handled by the model.
///
private void LoadSimulatedData()
{
// turn the item type enum into a list to use in the model
// so it can be displayed easily in a dropdown
foreach (var item in Enum.GetValues(typeof(ItemType)))
{
ItemTypes.Add(item.ToString());
}
SelectedItemType = null;
SelectedItem = null;
// Normally this would be a loop of your data output during a load event
// of some type, but for this tutorial we are just creating 9 static items
// add 3 foods
var item1 = new ItemData
{
name = "Apple",
type = ItemType.Food,
description = "A delicious apple",
value = 10,
icon = Resources.Load("DataBinding/Apple")
};
_masterItemList.Add(item1);
var item2 = new ItemData()
{
name = "Banana",
type = ItemType.Food,
description = "A delicious banana",
value = 15,
icon = Resources.Load("DataBinding/Banana")
};
_masterItemList.Add(item2);
var item3 = new ItemData()
{
name = "Pear",
type = ItemType.Food,
description = "A delicious pear",
value = 20,
icon = Resources.Load("DataBinding/Pear")
};
_masterItemList.Add(item3);
// add 3 weapons
var item4 = new ItemData()
{
name = "Sword",
type = ItemType.Weapon,
description = "A sharp sword",
value = 10,
icon = Resources.Load("DataBinding/Sword")
};
_masterItemList.Add(item4);
var item5 = new ItemData()
{
name = "Axe",
type = ItemType.Weapon,
description = "A trusty axe",
value = 15,
icon = Resources.Load("DataBinding/Axe")
};
_masterItemList.Add(item5);
var item6 = new ItemData()
{
name = "Long Bow",
type = ItemType.Weapon,
description = "A hunters long bow",
value = 20,
icon = Resources.Load("DataBinding/LongBow")
};
_masterItemList.Add(item6);
// add 3 armor
var item7 = new ItemData()
{
name = "Leather Armor",
type = ItemType.Armor,
description = "Sturdy Leather armor",
value = 10,
icon = Resources.Load("DataBinding/LeatherArmor")
};
_masterItemList.Add(item7);
var item8 = new ItemData()
{
name = "Chain Mail",
type = ItemType.Armor,
description = "Reliable Chain mail armor",
value = 15,
icon = Resources.Load("DataBinding/ChainMail")
};
_masterItemList.Add(item8);
var item9 = new ItemData()
{
name = "Plate Mail",
type = ItemType.Armor,
description = "Heavy Full Plate mail armor",
value = 20,
icon = Resources.Load("DataBinding/PlateMail")
};
_masterItemList.Add(item9);
SelectedItemType = nameof(ItemType.AllItems);
}
}
///
/// Defines the types of items that can be categorized and filtered within the application.
/// Used to classify and manage items based on their specific category.
///
public enum ItemType
{
AllItems,
Food,
Weapon,
Armor
}
///
/// Represents an item with associated metadata such as name, type, description, value, and icon.
///
[Serializable]
public class ItemData
{
public string name;
public ItemType type;
public string description;
public int value;
public Sprite icon;
}