public static IDynamic_UIView CreateDynamic_UIControl( UIViewController parentViewController, UIView parentView, Rock.Client.Attribute uiControlAttrib, bool required, string attribKey )
            {
                IDynamic_UIView createdControl = null;

                // first, get the field type
                switch ( uiControlAttrib.FieldType.Guid.ToString( ) )
                {
                    // Single-Select
                    case "7525c4cb-ee6b-41d4-9b64-a08048d5a5c0":
                    {
                        // now what KIND of single select is it? Find the attributeQualifier defining the field type
                        List<Rock.Client.AttributeQualifier> qualifers = uiControlAttrib.AttributeQualifiers.Cast<Rock.Client.AttributeQualifier>( ) as List<Rock.Client.AttributeQualifier>;
                        Rock.Client.AttributeQualifier fieldTypeQualifer = qualifers.Where( aq => aq.Key.ToLower( ) == "fieldtype" ).SingleOrDefault( );

                        // now get the values that the control will use.
                        Rock.Client.AttributeQualifier valuesQualifer = qualifers.Where( aq => aq.Key.ToLower( ) == "values" ).SingleOrDefault( );

                        // check for the known supported types
                        // Drop-Down List
                        if ( fieldTypeQualifer.Guid.ToString( ) == "62a411f9-5cec-492d-9bab-98f23b4df44c" )
                        {
                            // create a drop down
                            createdControl = new Dynamic_UIDropDown( parentViewController, parentView, uiControlAttrib, valuesQualifer, required, attribKey );
                        }
                        else if ( fieldTypeQualifer.Guid.ToString( ) == "" )
                        {
                            //todo: create a radio button
                        }
                        else
                        {
                            // here, show the value as WELL as the guid
                            Rock.Mobile.Util.Debug.WriteLine( string.Format( "Unknown single-select control type specified: {0}, Guid: {1}", fieldTypeQualifer.Value, fieldTypeQualifer.Guid ) );
                        }
                        break;
                    }

                    // Date Picker
                    case "6b6aa175-4758-453f-8d83-fcd8044b5f36":
                    {
                        createdControl = new Dynamic_UIDatePicker( parentViewController, uiControlAttrib.Name, required, attribKey );
                        break;
                    }

                    // Check Box (A Switch on iOS)
                    case "1edafded-dfe6-4334-b019-6eecba89e05a":
                    {
                        // now what KIND of single select is it? Find the attributeQualifier defining the field type
                        List<Rock.Client.AttributeQualifier> qualifers = uiControlAttrib.AttributeQualifiers.Cast<Rock.Client.AttributeQualifier>( ) as List<Rock.Client.AttributeQualifier>;

                        // now get the values that the control will use.
                        Rock.Client.AttributeQualifier falseQualifer = qualifers.Where( aq => aq.Key.ToLower( ) == "falsetext" ).SingleOrDefault( );
                        Rock.Client.AttributeQualifier trueQualifer = qualifers.Where( aq => aq.Key.ToLower( ) == "truetext" ).SingleOrDefault( );

                        //createdControl = new Dynamic_UISwitch( parentViewController, parentView, uiControlAttrib, falseQualifer.Value, trueQualifer.Value, required );
                        createdControl = new Dynamic_UIToggle( parentViewController, parentView, uiControlAttrib, falseQualifer.Value, trueQualifer.Value, required, attribKey );
                        break;
                    }

                    // Integer Input Field
                    case "a75dfc58-7a1b-4799-bf31-451b2bbe38ff":
                    {
                        createdControl = new Dynamic_UITextField( parentViewController, parentView, uiControlAttrib, true, required, attribKey );
                        break;
                    }

                    // Text Field
                    case "9c204cd0-1233-41c5-818a-c5da439445aa":
                    {
                        createdControl = new Dynamic_UITextField( parentViewController, parentView, uiControlAttrib, false, required, attribKey );
                        break;
                    }

                    default:
                    {
                        break;
                    }
                }

                return createdControl;
            }
            public override void ViewDidLoad( PersonInfoViewController parentViewController )
            {
                base.ViewDidLoad( parentViewController );

                // build the grade list.
                string[] gradeList = new string[ Config.Instance.SchoolGrades.Count ];
                for( int i = 0; i < Config.Instance.SchoolGrades.Count; i++ )
                {
                    gradeList[ i ] = Config.Instance.SchoolGrades[ i ].Description;
                }

                GradeDropDown = new Dynamic_UIDropDown( parentViewController, RootView, Strings.PersonInfo_GradeHeader, Strings.PersonInfo_GradeMessage, gradeList, false );
                RootView.AddSubview( GradeDropDown );

                // build the dynamic UI controls
                for( int i = 0; i < Config.Instance.PersonAttributeDefines.Count; i++ )
                {
                    // make sure this control is for a child
                    if ( Config.Instance.PersonAttributes[ i ][ "filter" ] == null || Config.Instance.PersonAttributes[ i ][ "filter" ].ToLower( ) == "child" )
                    {
                        // get the required flag and the attribs that define what type of UI control this is.
                        bool isRequired = bool.Parse( Config.Instance.PersonAttributes[ i ][ "required" ] );
                        Rock.Client.Attribute uiControlAttrib = Config.Instance.PersonAttributeDefines[ i ];

                        // build it and add it to our UI
                        IDynamic_UIView uiView = Dynamic_UIFactory.CreateDynamic_UIControl( parentViewController, RootView, uiControlAttrib, isRequired, Config.Instance.PersonAttributeDefines[ i ].Key );
                        if ( uiView != null )
                        {
                            if ( isRequired == true )
                            {
                                Dynamic_RequiredControls.Add( uiView );
                                Dynamic_RequiredControls[ Dynamic_RequiredControls.Count - 1 ].AddToView( RootView );
                            }
                            else
                            {
                                Dynamic_OptionalControls.Add( uiView );
                                Dynamic_OptionalControls[ Dynamic_OptionalControls.Count - 1 ].AddToView( RootView );
                            }

                            uiView.ShouldAdjustForKeyboard( true );
                        }
                    }
                }
            }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            View.Layer.Contents = Parent.View.Layer.Contents;
            View.BackgroundColor = Parent.View.BackgroundColor;

            // setup a scroll view
            ScrollView = new UIScrollViewWrapper();
            ScrollView.Layer.AnchorPoint = CGPoint.Empty;
            ScrollView.Parent = this;
            ScrollView.BackgroundColor = Theme.GetColor( Config.Instance.VisualSettings.SidebarBGColor );
            View.AddSubview( ScrollView );

            FamilyName = new Dynamic_UITextField( this, ScrollView, Strings.General_FamilyName, false, true );
            FamilyName.GetTextField( ).AutocorrectionType = UITextAutocorrectionType.No;
            FamilyName.GetTextField( ).AutocapitalizationType = UITextAutocapitalizationType.Words;
            FamilyName.AddToView( ScrollView );

            //TODO: Handle international
            AddressHeader = new UILabel();
            AddressHeader.Layer.AnchorPoint = CGPoint.Empty;
            AddressHeader.Text = Strings.General_HomeAddress;
            AddressHeader.Font = FontManager.GetFont( Settings.General_BoldFont, Config.Instance.VisualSettings.SmallFontSize );
            Theme.StyleLabel( AddressHeader, Config.Instance.VisualSettings.LabelStyle );
            ScrollView.AddSubview( AddressHeader );

            Street = new UIInsetTextField();
            Street.InputAssistantItem.LeadingBarButtonGroups = null;
            Street.InputAssistantItem.TrailingBarButtonGroups = null;
            Street.Layer.AnchorPoint = CGPoint.Empty;
            Street.Placeholder = Strings.General_Street;
            Street.Font = FontManager.GetFont( Settings.General_RegularFont, Config.Instance.VisualSettings.MediumFontSize );
            Theme.StyleTextField( Street, Config.Instance.VisualSettings.TextFieldStyle );
            Street.AutocorrectionType = UITextAutocorrectionType.No;
            Street.AutocapitalizationType = UITextAutocapitalizationType.Words;
            ScrollView.AddSubview( Street );

            City = new UIInsetTextField();
            City.InputAssistantItem.LeadingBarButtonGroups = null;
            City.InputAssistantItem.TrailingBarButtonGroups = null;
            City.Layer.AnchorPoint = CGPoint.Empty;
            City.Placeholder = Strings.General_City;
            City.Font = FontManager.GetFont( Settings.General_RegularFont, Config.Instance.VisualSettings.MediumFontSize );
            Theme.StyleTextField( City, Config.Instance.VisualSettings.TextFieldStyle );
            City.AutocorrectionType = UITextAutocorrectionType.No;
            City.AutocapitalizationType = UITextAutocapitalizationType.Words;
            ScrollView.AddSubview( City );

            State = new UIInsetTextField();
            State.InputAssistantItem.LeadingBarButtonGroups = null;
            State.InputAssistantItem.TrailingBarButtonGroups = null;
            State.Layer.AnchorPoint = CGPoint.Empty;
            State.Placeholder = Strings.General_State;
            State.Font = FontManager.GetFont( Settings.General_RegularFont, Config.Instance.VisualSettings.MediumFontSize );
            Theme.StyleTextField( State, Config.Instance.VisualSettings.TextFieldStyle );
            State.AutocorrectionType = UITextAutocorrectionType.No;
            State.AutocapitalizationType = UITextAutocapitalizationType.Words;
            ScrollView.AddSubview( State );

            PostalCode = new UIInsetTextField();
            PostalCode.InputAssistantItem.LeadingBarButtonGroups = null;
            PostalCode.InputAssistantItem.TrailingBarButtonGroups = null;
            PostalCode.Layer.AnchorPoint = CGPoint.Empty;
            PostalCode.Placeholder = Strings.General_Zip;
            PostalCode.Font = FontManager.GetFont( Settings.General_RegularFont, Config.Instance.VisualSettings.MediumFontSize );
            Theme.StyleTextField( PostalCode, Config.Instance.VisualSettings.TextFieldStyle );
            ScrollView.AddSubview( PostalCode );
            //

            // build an array with all the campuses
            string[] campuses = new string[ Config.Instance.Campuses.Count ];
            for ( int i = 0; i < Config.Instance.Campuses.Count; i++ )
            {
                campuses[ i ] = Config.Instance.Campuses[ i ].Name;
            }

            FamilyCampus = new Dynamic_UIDropDown( this, ScrollView, Strings.FamilyInfo_Select_Campus_Header, Strings.FamilyInfo_Select_Campus_Message, campuses, false );
            FamilyCampus.AddToView( ScrollView );

            //default the campus to whatever's selected by the app settings.
            FamilyCampus.SetCurrentValue( Config.Instance.Campuses[ Config.Instance.SelectedCampusIndex ].Name );

            // build the dynamic UI controls
            for( int i = 0; i < Config.Instance.FamilyAttributeDefines.Count; i++ )
            {
                // get the required flag and the attribs that define what type of UI control this is.
                bool isRequired = bool.Parse( Config.Instance.FamilyAttributes[ i ][ "required" ] );
                Rock.Client.Attribute uiControlAttrib = Config.Instance.FamilyAttributeDefines[ i ];

                // build it and add it to our UI
                IDynamic_UIView uiView = Dynamic_UIFactory.CreateDynamic_UIControl( this, ScrollView, uiControlAttrib, isRequired, Config.Instance.FamilyAttributeDefines[ i ].Key );
                if ( uiView != null )
                {
                    Dynamic_FamilyControls.Add( uiView );
                    Dynamic_FamilyControls[ Dynamic_FamilyControls.Count - 1 ].AddToView( ScrollView );
                }
            }

            KeyboardAdjustManager = new KeyboardAdjustManager( View );

            // save button goes last, BELOW the dynamic content
            SaveButton = UIButton.FromType( UIButtonType.System );
            SaveButton.Layer.AnchorPoint = CGPoint.Empty;
            SaveButton.SetTitle( Strings.General_Save, UIControlState.Normal );
            SaveButton.Font = FontManager.GetFont( Settings.General_RegularFont, Config.Instance.VisualSettings.SmallFontSize );
            Theme.StyleButton( SaveButton, Config.Instance.VisualSettings.PrimaryButtonStyle );
            SaveButton.SetTitleColor( UIColor.LightGray, UIControlState.Disabled );
            SaveButton.SizeToFit( );
            SaveButton.Bounds = new CGRect( 0, 0, SaveButton.Bounds.Width * 2.00f, SaveButton.Bounds.Height );
            ScrollView.AddSubview( SaveButton );

            SaveButton.TouchUpInside += (object sender, EventArgs e ) =>
                {
                    TrySubmitFamilyInfo( );
                };

            TableView = new UITableView( );
            TableView.Layer.AnchorPoint = CGPoint.Empty;
            TableView.BackgroundColor = UIColor.Clear;
            TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
            View.AddSubview( TableView );

            // if there's no family ID this is a new family, so create a table that lets them begin adding people
            if ( Family.Id == 0 )
            {
                TableView.Source = new TableSource( this );
            }

            // create the new person and add person view controllers
            PersonInfoViewController = new PersonInfoViewController( Parent );
            AddChildViewController( PersonInfoViewController );
            View.AddSubview( PersonInfoViewController.View );

            AddPersonViewController = new AddPersonViewController( Parent );
            AddChildViewController( AddPersonViewController );
            View.AddSubview( AddPersonViewController.View );

            BlockerView = new UIBlockerView( View, View.Bounds.ToRectF( ) );

            View.AddSubview( SaveResult );
        }