相关文章推荐
坚韧的闹钟  ·  创建表 | PingCAP 文档中心·  5 月前    · 
儒雅的椅子  ·  VB6.0 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have an order status property that is an enum, and I would like to change what XAML is displayed based on the enum value.

Is that possible?

Here is my XAML with all my layouts I've been working on (some commented out):

<?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:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
    x:Class="Divco.OrderPage"
    Title="Order">
<ContentPage.BindingContext>
</ContentPage.BindingContext>
<ContentPage.Content>
    <!-- Basic stack layout used in all order views -->
    <StackLayout>
        <!--<StackLayout.Style>-->
            <!-- Needs Driver -->
            <!--<StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="150"
                    x:Name="WaitingMap"
                    IsShowingUser="false"
                    MapType="Street" />
            </StackLayout>
            <StackLayout Padding="20, 0, 20, 0">
                <Label Text="{Binding CurrentOrder.Description}" LineBreakMode="WordWrap" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Pickup" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Dropoff" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                <Button Text="Navigate!" 
                        BackgroundColor="Fuschia" 
                        TextColor="White" 
                        Font="Bold,20"
                        Grid.Row="0" Grid.Column="1" />
            </StackLayout>-->
            <!-- Waiting Driver -->
            <!--<StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="200"
                    x:Name="WaitingMap"
                    IsShowingUser="true"
                    MapType="Street" />
            </StackLayout>
            <StackLayout VerticalOptions="CenterAndExpand" Padding="20, 0, 20, 0" >
                <Label Text="Pickup" TextColor="Fuchsia" Font="Bold" />
                <Label Text="{Binding CurrentOrder.PickupContact.Display}"/>
                <Label Text="{Binding CurrentOrder.PickupAddress.Display}"/>
                <Label Text="{Binding CurrentOrder.PickupTimeFormatted}"/>
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                    <Grid.RowDefinitions>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button Text="Navigate" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="0"/>
                    <Button Text="Call" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="1"/>
                </Grid>
                <Button Text="I'm here!" 
                            BackgroundColor="Fuschia" 
                            TextColor="White" 
                            Font="Bold,20" />
            </StackLayout>-->
            <!-- Intransit -->
            <!--<StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="200"
                    x:Name="TransitMap"
                    IsShowingUser="true"
                    MapType="Street" />
            </StackLayout>
            <StackLayout VerticalOptions="CenterAndExpand" Padding="20, 0, 20, 0" >
                <Label Text="Dropoff" TextColor="Fuchsia" Font="Bold" />
                <Label Text="{Binding CurrentOrder.DropoffContact.Display}"/>
                <Label Text="{Binding CurrentOrder.DropoffAddress.Display}"/>
                <Label Text="{Binding CurrentOrder.DropoffTimeFormatted}"/>
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                    <Grid.RowDefinitions>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button Text="Navigate" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="0"/>
                    <Button Text="Call" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="1"/>
                </Grid>
                <Button Text="I'm here!" 
                            BackgroundColor="Fuschia" 
                            TextColor="White" 
                            Font="Bold,20" />
            </StackLayout>-->
            <!-- Needs Signature -->
            <!--<StackLayout VerticalOptions="CenterAndExpand" Padding="20, 20, 20, 20">
                <Label Text="In order to verify the identity of the signature, please take a photo of the recipient's ID." HorizontalTextAlignment="Center"/> 
                <Button Text="Take Picture"
                    BackgroundColor="Gray" 
                    TextColor="White" 
                    Font="Bold,20"/>
                <Button Text="Sign" 
                    BackgroundColor="Fuschia" 
                    TextColor="White" 
                    Font="Bold,20" IsEnabled="false"/>
            </StackLayout>-->
            <!-- Complete! -->
            <StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="150"
                    x:Name="WaitingMap"
                    IsShowingUser="false"
                    MapType="Street" />
            </StackLayout>
            <StackLayout Padding="20, 0, 20, 0">
                <Label Text="{Binding CurrentOrder.Description}" LineBreakMode="WordWrap" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Pickup" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Dropoff" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                <Label Text="This order is complete! Great work!" HorizontalTextAlignment="Center" TextColor="Fuchsia" Font="Bold"/>
            </StackLayout>
        <!--</StackLayout.Style>-->
    </StackLayout>
</ContentPage.Content>

So, for example I would like the following to display when the order status is "InTransit":

<!-- Intransit -->
            <!--<StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="200"
                    x:Name="TransitMap"
                    IsShowingUser="true"
                    MapType="Street" />
            </StackLayout>
            <StackLayout VerticalOptions="CenterAndExpand" Padding="20, 0, 20, 0" >
                <Label Text="Dropoff" TextColor="Fuchsia" Font="Bold" />
                <Label Text="{Binding CurrentOrder.DropoffContact.Display}"/>
                <Label Text="{Binding CurrentOrder.DropoffAddress.Display}"/>
                <Label Text="{Binding CurrentOrder.DropoffTimeFormatted}"/>
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                    <Grid.RowDefinitions>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button Text="Navigate" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="0"/>
                    <Button Text="Call" 
                            BackgroundColor="Gray" 
                            TextColor="White" 
                            Font="Bold" 
                            Grid.Row="0" Grid.Column="1"/>
                </Grid>
                <Button Text="I'm here!" 
                            BackgroundColor="Fuschia" 
                            TextColor="White" 
                            Font="Bold,20" />
            </StackLayout>-->

VS the following when the order is "complete":

<!-- Complete! -->
            <StackLayout>
                <maps:Map WidthRequest="320" HeightRequest="150"
                    x:Name="WaitingMap"
                    IsShowingUser="false"
                    MapType="Street" />
            </StackLayout>
            <StackLayout Padding="20, 0, 20, 0">
                <Label Text="{Binding CurrentOrder.Description}" LineBreakMode="WordWrap" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Pickup" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.PickupTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="Dropoff" TextColor="Fuchsia" Font="Bold,14" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffContact.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffAddress.Display}" Font="12" HorizontalTextAlignment="Center" />
                <Label Text="{Binding CurrentOrder.DropoffTimeFormatted}" Font="12" HorizontalTextAlignment="Center" />
            </StackLayout>
            <StackLayout VerticalOptions="EndAndExpand" Padding="20, 0, 20, 20">
                <Label Text="This order is complete! Great work!" HorizontalTextAlignment="Center" TextColor="Fuchsia" Font="Bold"/>
            </StackLayout>

Here is the Order class for reference:

public class Order : INotifyPropertyChanged
    // event to handle changes in the order status 
    public event PropertyChangedEventHandler PropertyChanged;
    public enum Status { Preview, NeedsDriver, WaitingDriver, InTransit, NeedsSignature, Complete, Refunded }
    public string ID { get; set; }
    public string Description { get; set; }
    private Status _orderStatus;
    public Status OrderStatus { 
            return _orderStatus;
            _orderStatus = value;
            // tell the view that the order status has changed 
            OnPropertyChanged("OrderStatus");
    public Contact PickupContact { get; set; }
    public Contact DropoffContact { get; set; }
    public Address PickupAddress { get; set; }
    public Address DropoffAddress { get; set; }
    public DateTime PickupTime { get; set; }
    public DateTime DropoffTime { get; set; }
    // Formatted Pickup and Dropoff Times
    public string PickupTimeFormatted
        get { return PickupTime.ToString("g"); }
    public string DropoffTimeFormatted
        get { return DropoffTime.ToString("g"); }
    public Order()
    // Handler to tell the view that the order status has changed 
    protected void OnPropertyChanged(string name)
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(name));
    public override string ToString()
        return string.Format("[Order: ID={0}, Description={1}, OrderStatus={2}, PickupContact={3}, DropoffContact={4}, PickupAddress={5}, DropoffAddress={6}, PickupTime={7}, DropoffTime={8}, PickupTimeFormatted={9}, DropoffTimeFormatted={10}]", ID, Description, OrderStatus, PickupContact, DropoffContact, PickupAddress, DropoffAddress, PickupTime, DropoffTime, PickupTimeFormatted, DropoffTimeFormatted);

So you want to display parts of the UI depending on the value of an enum in your view model ?

There are multiple ways to do that, here are a few:

  • Put all the possible values in a container (a Grid, a StackLayout, an AbsoluteLayout and bind their IsVisible property to the enum using a converter that will convert your enum value to true or false
  • Same as 1., but use a DataTrigger, no need for any converter. This require moving the Order enum out of the class as Xaml can't reference nested types, and defining a custom xmlns ("yourNs" in the following example):
  • <!-- InTransit -->
    <StackLayout IsVisible="false"...>
      <StackLayout.Triggers>
        <DataTrigger TargetType="VisualElement" Binding="{Binding OrderStatus}" Value="{x:Static yourNs:Status.InTransit}">
          <Setter Property="IsVisible" Value="true" />
        </DataTrigger>
      </StackLayout.Triggers> 
    </StackLayout>
    <!-- Complete -->
    <StackLayout IsVisible="false">
      <StackLayout.Triggers>
        <DataTrigger TargetType="VisualElement" Binding="{Binding OrderStatus}" Value="{x:Static yourNs:Status.Complete}">
          <Setter Property="IsVisible" Value="true" />
        </DataTrigger>
      </StackLayout.Triggers> 
    </StackLayout>
    
  • If you have multiple status, and each view is complex, 1. or 2. will make a huge Xaml, and even though some parts are not visible, the Xaml is still parsed and the peer objects created. The best option is probably to define a Xaml view for each case, and depending on the enum value, set the right instance as the view content, using code behind or a DataTemplateSelector if you insist of going Xaml for everything.
  • I assume the enums you're trying to display are those:

    <Label Text="{Binding CurrentOrder.DropoffContact.Display}" .../>
    

    and the enum being DropoffContact. If I'm wrong, please correct me.

    In this case the Label will display "Display", as it's the string representation of the enum value (equivalent to what you'd have with ToString()).

    If you want to customize the text displayed for an enum value in a Binding, you can use a converter, differed e.g. like this:

    public class MyEnumConverter : IValueConverter
        public object ConvertTo (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            if (!(value is DropoffContact))
                return value;
            switch (DropoffContact)value) {
            case DropoffContact.Display:
                return "Some string representation"
            default:
                return value;
        public void ConvertFrom (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            thrown new NotImplementedException();
    

    Add that converter to your Xaml page as Resource, and use it in the binding:

    <Label Text="{Binding CurrentOrder.DropoffContact.Display, Converter={StaticResource myResourceKey}}" .../>
                    Thank you for your response, I updated my question in hopes of clarifying what I am asking. I hope this helps.
    – Edie W.
                    Mar 7, 2017 at 1:45
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.