0
votes

I am attempting to build a scaled buttons response for a series of questions using Xamarin Form v2.3.2.127. I am implementing it as ListView and have a number of buttons representing possible scaled response.

We are experiencing an issue where iOS platform does not set BackgroundColor property on a button inside the ListView but code does work on the Android platform. Inside the XAML Xamarin Forms here is the definition of the button itself (i omitted ListView cell definition for brevity):

<ListView x:Name="Questions"
              AutomationId="ListViewQuestions"
              SeparatorVisibility="None"
              ItemsSource="{Binding Questions}"
              ListView.HasUnevenRows="True"
              BackgroundColor="Transparent" >
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
              <StackLayout Orientation="Horizontal">
                <Label Text="{Binding KeyAndQuestion}" />
              </StackLayout>
              <StackLayout Orientation="Horizontal"
                  HorizontalOptions="Center">
              <controls:ScaleButton
                    Text="0"
                    AutomationId="ButtonWeightedZero"
                    HeightRequest="37"
                    WidthRequest="37"
                    TextColor="White"
                    FontAttributes="Bold"
                    BorderRadius="5"
                    BackgroundColor="#919191"
                    Command="{Binding WeightedQuestionAnswered}"
                    CommandParameter="0">
                  <controls:ScaleButton.Triggers>
                    <DataTrigger  TargetType="controls:ScaleButton"
                                  Binding="{Binding SelectedWeight}"
                                  Value="{x:Null}">
                      <Setter Property="BackgroundColor"
                              Value="#919191"/>
                    </DataTrigger>
                    <DataTrigger  TargetType="controls:ScaleButton"
                                  Binding="{Binding SelectedWeight}"
                                  Value="0">
                      <Setter Property="BackgroundColor"
                              Value="#007AC3"/>
                    </DataTrigger>
                  </controls:ScaleButton.Triggers>
                </controls:ScaleButton>
.... // other scale buttons
               </StackLayout>
           </StackLayout>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

Custom ScaledButton definition is straight forward as well.

public class ScaleButton : Button
{
}

I figured before I follow the Xamarin Bugzilla route, i would see if anyone experienced this.

Update

The the bound property is an integer and thus DataTrigger with Binding where x:Nil seems to be the culprit. Thus, I ended up refactoring the Scale button as follows.

<controls:ScaleButton
                Text="0"
                AutomationId="ButtonWeightedZero"
                Style="{StaticResource ScaleButton}"
                Command="{Binding WeightedQuestionAnswered}"
                CommandParameter="0">
              <controls:ScaleButton.Triggers>
                <DataTrigger  TargetType="controls:ScaleButton"
                              Binding="{Binding SelectedWeight}"
                              Value="0">
                  <Setter Property="Style"
                          Value="{StaticResource ScaleButtonSelected}"/>
                </DataTrigger>
              </controls:ScaleButton.Triggers>
</controls:ScaleButton>

Where Global resoure dictionary for the styles was set to this

<Style TargetType="{x:Type Button}" x:Key="ScaleButton" ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor" Value="#656665" />
    <Setter Property="FontAttributes" Value="Bold" />
    <Setter Property="HorizontalOptions" Value="Center" />
    <Setter Property="TextColor" Value="White" />
    <Setter Property="VerticalOptions" Value="Center" />
    <Setter Property="WidthRequest" Value="37" />
    <Setter Property="HeightRequest" Value="37" />
    <Setter Property="BorderRadius" Value="5" />
</Style>
<Style TargetType="{x:Type Button}" x:Key="ScaleButtonSelected" ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor" Value="#007AC3" />
    <Setter Property="FontAttributes" Value="Bold" />
    <Setter Property="HorizontalOptions" Value="Center" />
    <Setter Property="TextColor" Value="White" />
    <Setter Property="VerticalOptions" Value="Center" />
    <Setter Property="WidthRequest" Value="37" />
    <Setter Property="HeightRequest" Value="37" />
    <Setter Property="BorderRadius" Value="5" />
</Style>

This works on both platforms but the funny part is that trying to use the Setter on just the BackgroundColor only works on Android platform.

1

1 Answers

0
votes

Here is what I ended up doing which seems to work a lot better. I built a custom Weight value to Style converter and bound to Style property.

public class ScaleToStyleConverter : IValueConverter
{
    static ScaleToStyleConverter Instance = new ScaleToStyleConverter();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int paramValue;

        if (parameter == null)
            throw new ArgumentNullException("parameter");

        if (!(parameter is string))
            throw new ArgumentException("the parameter is not a string", "parameter");

        if (!int.TryParse((string)parameter, out paramValue))
        {
            throw new ArgumentException("The parameter cannot be converted to an integer.", "parameter");
        }

        return paramValue != (int)value ? 
            Application.Current.Resources["ScaleButton"] : 
            Application.Current.Resources["ScaleButtonSelected"];

    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

So the Xaml definition for the ScaleButton is as follows.

<controls:ScaleButton
                    Text="0"
                    AutomationId="ButtonWeightedZero"
                    Style="{Binding SelectedWeight, Converter= {x:Static converters:ScaleToStyleConverter.Instance }, ConverterParameter=0 }"
                    Command="{Binding WeightedQuestionAnswered}"
                    CommandParameter="0">
</controls:ScaleButton>

That seems to work quite well.