Martin Rohwedder
Martin Rohwedder

Reputation: 1751

Binding property to RelativeLayout.XConstraint in XAML Xamarin Forms

I have a problem with binding a property value from my Model objects to the RelativeLayout.XConstraint property in XAML.

I got a model, with a property called public int StartLocation { get; set; }, but if I bind this property to my RelativeLayout.XConstraint on a simple BoxView element, it doesnt set the X Constraint Property. I first tried doing this

<RelativeLayout BindableLayout.ItemsSource="{Binding Broadcasts}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <BoxView BackgroundColor="PaleVioletRed" RelativeLayout.XConstraint="{Binding StartLocation}" WidthRequest="{Binding Length}" HeightRequest="60" />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</RelativeLayout>

I got two bindings here. StartLocation and Length, and the Length Binding works fine, but with this approach it sets the BoxView elements xConstraint to the start (I think it is the relative X position 0).

I also tried this approach

<RelativeLayout BindableLayout.ItemsSource="{Binding Broadcasts}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <BoxView BackgroundColor="PaleVioletRed" RelativeLayout.XConstraint="{ConstraintExpression Constant={Binding StartLocation}}" WidthRequest="{Binding Length}" HeightRequest="60" />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</RelativeLayout>

Here I get an error when I run my code saying Cannot assign property "Constant": Property does not exist, or is not assignable, or mismatching type between value and property

Cannot assign property "Constant": Property does not exist, or is not assignable, or mismatching type between value and property

I hope someone can help me with this problem. Thanks in advance.

Upvotes: 1

Views: 781

Answers (1)

Derrick Wright
Derrick Wright

Reputation: 114

So I have been wrestling with a similar issue for some time now. I managed to solve it today with a neat workaround. Here's what I did:

(Xaml)

            <RelativeLayout x:Name="aviGroup" BindingContext="this"
               RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=X, Factor=1, Constant=1000}"
               RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Factor=1, Constant=25}">

                <Grid x:Name="aviGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Button x:Name="Settings" Text="more" BackgroundColor="Transparent" ImageSource="{local2:ImageResource Buddy.Images.settings_icon.png}" TextColor="Transparent" Clicked="Settings_Clicked" Padding="0" HorizontalOptions="EndAndExpand" Grid.Row="0" Grid.Column="1"/>

                    <BoxView x:Name="buttonBorder" BackgroundColor="White" HeightRequest="54" WidthRequest="54" CornerRadius="24" Margin="5" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" Grid.Row="0" Grid.Column="0" />

                    <ImageButton x:Name="userAvi" Source="{DynamicResource currentAVI}" Clicked="userAvi_Clicked" HorizontalOptions="Center" VerticalOptions="FillAndExpand" HeightRequest="48" WidthRequest="48" CornerRadius="22" Aspect="AspectFill" Margin="8" Grid.Row="0" Grid.Column="0"/>
                </Grid>

            </RelativeLayout>

(Code behind)

        private void cV_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (this.Width > 100)
            {

                if (Settings.X > 0) 
                {

                    PostX = Application.Current.MainPage.Width - 300;

                    Constraint newX = Constraint.Constant(PostX);

                    RelativeLayout.SetXConstraint(aviGroup, newX);                  

                }
              
            }
        }

Explanation: I have a trigger raised when my content view is resized, which calls cV_PropertyChanged. In this method, I calculate where I want the new x to be, create a new constraint with this value, and then call RelativeLayout.SetXConstraint with the view I want to bind and its new value.

This may not fit your project 1:1, but I hope you can make use of this workaround as well.

Cheers!

Upvotes: 1

Related Questions