Getting StateLayout with CustomState to show image thumbnail

258 Views Asked by At

In my Xamarin Forms 5 app, I have a form users will fill out to create a post -- similar to Facebook posts.

The effect I'm trying to create is this:

There's an "Add Image" button that allows user to upload an image. Once the image is uploaded, I want to no longer display the button but display a thumbnail version of the uploaded image.

Here's what my XAML looks like:

<StackLayout
   xct:StateLayout.CurrentState="{Binding MainState.None}"
   xct:StateLayout.CurrentCustomStateKey="{Binding PostImageState}">
      <xct:StateLayout.StateViews>
          <xct:StateView StateKey="Custom" CustomStateKey="Image set">
              <Image
                   Grid.Row="0"
                   Grid.Column="0"
                   Source="{Binding PostImageUrl}"
                   WidthRequest="30"
                   HeightRequest="30"/>
          </xct:StateView>
      </xct:StateLayout.StateViews>
      <Button
         Text="Add Image"
         Command="{Binding AddImageCommand}"
         BackgroundColor="{StaticResource SecondaryBackground}"
         WidthRequest="100"
         HeightRequest="35"
         HorizontalOptions="Start"
         Margin="10,0,0,0"/>
</StackLayout>

Here's an abbreviated version of my view model:

public class MyViewModel : BaseViewModel
{
   public LayoutState _mainState;
   string postImageUrl { get; set; }
   string postImageState { get; set; } = "No image";

   public MyViewModel()
   {
       Title = string.Empty;
       IsBusy = true;
       MainState = LayoutState.None;

       AddImageCommand = new AsyncCommand(Add_Image_Tapped);
   }

   public LayoutState MainState
   {
       get => _mainState;
       set => SetProperty(ref _mainState, value);
   }

   public string PostImageUrl
   {
       get => postImageUrl;
       set
       {
           if (postImageUrl == value)
               return;

           postImageUrl = value;
           OnPropertyChanged();
       }
   }

   public string PostImageState
   {
      get => postImageState;
      set
      {
          if (postImageState == value)
              return;

          postImageState = value;
          OnPropertyChanged();
      }
   }

   async Task Add_Image_Tapped()
   {
       // Upload image
       // Once upload is done
       PostImageUrl = uploadedFileUrl;
       PostImageState = "Image set";
   }
}

I haven't been able to get this to work. Currently, it's not even showing the "Add Image" button. Where am I making a mistake?

1

There are 1 best solutions below

0
On

There are several problems with your code.

1.Since you use Binding for xct:StateLayout.CurrentState, we should bind it to a variable in ViewModel, here we should use MainState not MainState.None:

   xct:StateLayout.CurrentState="{Binding MainState}"

2.Based on your requirement, we can use the value from LayoutState enumeration(for example StateKey="Success"),, we don't need add custom states.

3.If we want to hidden the button once uploading the image, we can bind MainState to property IsVisible of button , but need use Converter StateToBooleanConverter to convert State to bool.

Based on your code ,I created a simple demo, and it works properly on my side. You can refer to the following code:

MyPage.Xaml

   <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xct="http://xamarin.com/schemas/2020/toolkit" 
             xmlns:viewmodel="clr-namespace:FormApp0314.ViewModel"
             x:Class="FormApp0314.TestPage1">

    <ContentPage.BindingContext>
        <viewmodel:MyViewModel></viewmodel:MyViewModel>
    </ContentPage.BindingContext>

    <ContentPage.Resources>
        <xct:StateToBooleanConverter x:Key="StateToBooleanConverter" />
    </ContentPage.Resources>
    <StackLayout
       xct:StateLayout.CurrentState="{Binding MainState}">
        <xct:StateLayout.StateViews>
            <xct:StateView StateKey="Success" CustomStateKey="Image set">
                <Image 
                   Grid.Row="0"
                   Grid.Column="0"
                   Source="{ Binding PostImageUrl}"
                   WidthRequest="60"
                   HeightRequest="60"/>
            </xct:StateView>
        </xct:StateLayout.StateViews>

       <Button
         Text="Add Image"
         Command="{Binding AddImageCommand}"
            
         IsVisible="{Binding MainState, Converter={StaticResource StateToBooleanConverter}, ConverterParameter={x:Static xct:LayoutState.None}}"
         WidthRequest="100"
         HeightRequest="35"
         HorizontalOptions="Start"
         Margin="10,0,0,0" />

     </StackLayout>

</ContentPage>

MyViewModel.cs

public class MyViewModel: BaseViewModel
{
    public LayoutState _mainState;
    string postImageUrl;
    string postImageState  = "No image";

    public ICommand AddImageCommand { get; }

    public MyViewModel()
    {

        MainState = LayoutState.None;

        PostImageUrl = "bell.png";


        AddImageCommand = CommandFactory.Create(Add_Image_Tapped);
    }

    async Task Add_Image_Tapped()
    {

        MainState = LayoutState.Success;
        await Task.Delay(3000);

        MainState = LayoutState.None;

    }



    public LayoutState MainState
    {
        get => _mainState;
        set => SetProperty(ref _mainState, value);
    }

    public string PostImageUrl
    {
        get => postImageUrl;
        set => SetProperty(ref postImageUrl, value);
    }



    public string PostImageState
    {
        get => postImageState;
        set => SetProperty(ref postImageState, value);
    }
}