File: RadioButton\RadioButtonGroupController.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System;
 
namespace Microsoft.Maui.Controls
{
	internal class RadioButtonGroupController
	{
		readonly Element _layout;
		string _groupName;
		private object _selectedValue;
 
		public string GroupName { get => _groupName; set => SetGroupName(value); }
		public object SelectedValue { get => _selectedValue; set => SetSelectedValue(value); }
 
		public RadioButtonGroupController(Maui.ILayout layout)
		{
			if (layout is null)
			{
				throw new ArgumentNullException(nameof(layout));
			}
 
			_layout = (Element)layout;
			_layout.ChildAdded += ChildAdded;
 
			if (!string.IsNullOrEmpty(_groupName))
			{
				UpdateGroupNames(_layout, _groupName);
			}
 
#pragma warning disable CS0618 // TODO: Remove when we internalize/replace MessagingCenter
			MessagingCenter.Subscribe<RadioButton, RadioButtonGroupSelectionChanged>(this,
				RadioButtonGroup.GroupSelectionChangedMessage, HandleRadioButtonGroupSelectionChanged);
			MessagingCenter.Subscribe<RadioButton, RadioButtonGroupNameChanged>(this, RadioButton.GroupNameChangedMessage,
				HandleRadioButtonGroupNameChanged);
			MessagingCenter.Subscribe<RadioButton, RadioButtonValueChanged>(this, RadioButton.ValueChangedMessage,
				HandleRadioButtonValueChanged);
#pragma warning restore CS0618 // Type or member is obsolete
		}
 
		bool MatchesScope(RadioButtonScopeMessage message)
		{
			return RadioButtonGroup.GetVisualRoot(_layout) == message.Scope;
		}
 
		void HandleRadioButtonGroupSelectionChanged(RadioButton selected, RadioButtonGroupSelectionChanged args)
		{
			if (selected.GroupName != _groupName || !MatchesScope(args))
			{
				return;
			}
 
			_layout.SetValue(RadioButtonGroup.SelectedValueProperty, selected.Value);
		}
 
		void HandleRadioButtonGroupNameChanged(RadioButton radioButton, RadioButtonGroupNameChanged args)
		{
			if (args.OldName != _groupName || !MatchesScope(args))
			{
				return;
			}
 
			_layout.ClearValue(RadioButtonGroup.SelectedValueProperty);
		}
 
		void HandleRadioButtonValueChanged(RadioButton radioButton, RadioButtonValueChanged args)
		{
			if (radioButton.GroupName != _groupName || !MatchesScope(args))
			{
				return;
			}
 
			_layout.SetValue(RadioButtonGroup.SelectedValueProperty, radioButton.Value);
		}
 
		void ChildAdded(object sender, ElementEventArgs e)
		{
			if (string.IsNullOrEmpty(_groupName))
			{
				return;
			}
 
			if (e.Element is RadioButton radioButton)
			{
				AddRadioButton(radioButton);
			}
			else
			{
				foreach (var element in e.Element.Descendants())
				{
					if (element is RadioButton radioButton1)
					{
						AddRadioButton(radioButton1);
					}
				}
			}
		}
 
		void AddRadioButton(RadioButton radioButton)
		{
			UpdateGroupName(radioButton, _groupName);
 
			if (radioButton.IsChecked)
			{
				_layout.SetValue(RadioButtonGroup.SelectedValueProperty, radioButton.Value);
			}
 
			if (object.Equals(radioButton.Value, this.SelectedValue))
			{
				radioButton.SetValue(RadioButton.IsCheckedProperty, true, specificity: SetterSpecificity.FromHandler);
			}
		}
 
		void UpdateGroupName(Element element, string name, string oldName = null)
		{
			if (!(element is RadioButton radioButton))
			{
				return;
			}
 
			var currentName = radioButton.GroupName;
 
			if (string.IsNullOrEmpty(currentName) || currentName == oldName)
			{
				radioButton.GroupName = name;
			}
		}
 
		void UpdateGroupNames(Element element, string name, string oldName = null)
		{
			foreach (Element descendant in element.Descendants())
			{
				UpdateGroupName(descendant, name, oldName);
			}
		}
 
		void SetSelectedValue(object radioButtonValue)
		{
			_selectedValue = radioButtonValue;
 
			if (radioButtonValue != null)
			{
#pragma warning disable CS0618 // TODO: Remove when we internalize/replace MessagingCenter
				MessagingCenter.Send<Element, RadioButtonGroupValueChanged>(_layout, RadioButtonGroup.GroupValueChangedMessage,
					new RadioButtonGroupValueChanged(_groupName, RadioButtonGroup.GetVisualRoot(_layout), radioButtonValue));
#pragma warning restore CS0618 // Type or member is obsolete
			}
		}
 
		void SetGroupName(string groupName)
		{
			var oldName = _groupName;
			_groupName = groupName;
			UpdateGroupNames(_layout, _groupName, oldName);
		}
	}
}