Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Forms State Container View not Respecting Layout Options

I am using a basic State Management system found here: (code below)

https://github.com/xDelivered-Patrick/Xamarin.Forms.Essentials/blob/master/Essentials/Controls/State/StateContainer.cs

When implementing, my XAML View looks like the below.

The problem is the StackLayout CenterAndExpand is not working. All the views when rendered are simply scrunched at the top.

If I pull the particular section out of the StateContainer and eliminate its usage, it renders correctly. Is this an issue with the way the View is being rendered inside the Content of the StateContainer?

EDIT: Here is a minimal example: https://github.com/aherrick/StateManagementDemo

XAML:

<ContentPage.Content>

    <StackLayout x:Name="layoutWrap" VerticalOptions="FillAndExpand"
                  HorizontalOptions="FillAndExpand">

        <controls:StateContainer State="{Binding State}">
            <controls:StateCondition Is="Loading">

                <StackLayout Orientation="Vertical" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">

                    <ActivityIndicator  x:Name="loadingIndicator"
                                    IsVisible="{Binding IsBusy}"
                                    IsRunning="{Binding IsBusy}"
                  VerticalOptions="FillAndExpand"
                  HorizontalOptions="FillAndExpand" />
                </StackLayout>
            </controls:StateCondition>

            <controls:StateCondition Is="Loaded">
                <!-- actual content here -->
            </controls:StateCondition>
            <controls:StateCondition Is="Error">

                <StackLayout Orientation="Vertical" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">

                    <Label FontAttributes="Bold" Text="Oops! There was a problem."  VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
                    <Button Text="Tap to Retry" Command="{Binding LoadVenuesCommand}" CommandParameter="true"   HorizontalOptions="CenterAndExpand" TextColor="White" Padding="15"  BackgroundColor="#26265E" />
                </StackLayout>
            </controls:StateCondition>
        </controls:StateContainer>
    </StackLayout>
</ContentPage.Content>

C#

[ContentProperty("Content")]
[Preserve(AllMembers = true)]
public class StateCondition : View
{
    public object Is { get; set; }
    public object IsNot { get; set; }
    public View Content { get; set; }
}

[ContentProperty("Conditions")]
[Preserve(AllMembers = true)]
public class StateContainer : ContentView
{
    public List<StateCondition> Conditions { get; set; } = new List<StateCondition>();

    // https://forums.xamarin.com/discussion/102024/change-bindableproperty-create-to-bindableproperty-create
    //public static readonly BindableProperty StateProperty = BindableProperty.Create(nameof(State), typeof(object), typeof(StateContainer), propertyChanged: StateChanged);

    public static readonly BindableProperty StateProperty = BindableProperty.Create<StateContainer, object>(x => x.State, null, propertyChanged: StateChanged);

    public static void Init()
    {
    }

    private static void StateChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var parent = bindable as StateContainer;
        parent?.ChooseStateProperty(newValue);
    }

    public object State
    {
        get { return GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    private void ChooseStateProperty(object newValue)
    {
        foreach (StateCondition stateCondition in Conditions)
        {
            if (stateCondition.Is != null)
            {
                if (stateCondition.Is.ToString().Equals(newValue.ToString()))
                {
                    Content = stateCondition.Content;
                }
            }
            else if (stateCondition.IsNot != null)
            {
                if (!stateCondition.IsNot.ToString().Equals(newValue.ToString()))
                {
                    Content = stateCondition.Content;
                }
            }
        }
    }
}
like image 939
aherrick Avatar asked Nov 11 '18 16:11

aherrick


1 Answers

The solution is simple but not obvious. Add HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" to the <local:StateContainer> object as well. All Xamarin Forms LayoutOptions ending with ...AndExpand can olny expand if their containing parent allows it. That is why it worked when you removed the element from the <local:StateContainer> and put it directly in the StackLayout that allready had FillAndExpand declared thereby "allowing expansion".

like image 122
Alexander Uddfeldt Avatar answered Oct 13 '22 16:10

Alexander Uddfeldt