Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Databinding into grid's columnDefinition width

TrixoTrixo Member ✭✭

Hi, I am having problems with binding into grid's columndefinition width proprety.
I tried TestWidth.Value as well as just double and string.
Any idea whats the problem?

`<ColumnDefinition Width="{Binding Parent.SizeModifier.TestWidth, Source={x:Reference Self}}"></ColumnDefinition>`

    class SizeModifier
    {
        public int DefaultWindowWidth { get; set; }
        public int DefaultWindowHeight { get; set; }
        public int DefaultWindowDPI { get; set; }
        public double WidthModifier { get; set; }
        public double HeightModifier { get; set; }
        public double DPIModifier { get; set; }
        public int DeviceWidth { get; set; }
        public int DeviceHeight { get; set; }
        public int DeviceDPI { get; set; }
        public GridLength TestWidth { get; set; }
        public string Test = "400";

        public SizeModifier()
        {
            DefaultWindowWidth = 1280;
            DefaultWindowHeight = 800;
            DefaultWindowDPI = 160;
            DeviceDPI = DependencyService.Get<IGetScreenSizes>().GetDisplayDpi();
            DeviceWidth = DependencyService.Get<IGetScreenSizes>().GetDisplayWidth();
            DeviceHeight = DependencyService.Get<IGetScreenSizes>().GetDisplayHeight();
            DPIModifier = (double)DeviceDPI / (double)DefaultWindowDPI;
            WidthModifier = (double)DeviceWidth / (double)DefaultWindowWidth*DPIModifier;
            HeightModifier = (double)DeviceHeight / (double)DefaultWindowHeight*DPIModifier;
            TestWidth = new GridLength((double)400 * WidthModifier, GridUnitType.Absolute);

        }
    }


}

Posts

  • Amar_BaitAmar_Bait DZMember ✭✭✭✭✭
    edited July 2019

    Binding requires a declared static BindableProperty (that has the same name as the backing property plus "Property" suffix)

    public static BindableProperty TestWidth**Property** = BindableProperty.Create(nameof(TestWidth), typeof(GridLength), typeof(SizeModifier), defaultValue: GridLength.Star);
    
    public GridLength TestWidth 
    {
        get =>(GridLength)GetValue(TestWidthProperty);
        set => SetValue(TestWidthProperty, value);
    }
    
  • TrixoTrixo Member ✭✭

    @Amar_Bait This is not a problem. I have used same structure to bind the values. Everything else works, but SizeModifier.

    app.xaml.cs
     ApplicationBindings ApplicationBind { get; set; }
    
    applicationBindings
        class ApplicationBindings
        {
            public Navigation AppNavigation { get; set; }
            public Battery BatteryStatus { get; set; }
            public UserData UserData { get; set; }
            public DeviceData DeviceData { get; set; }
            public VitalsData VitalsData { get; set; }
            public SizeModifier SizeModifier { get; set; }
        }
    
  • TrixoTrixo Member ✭✭

    In boxview's widthrequest following works.
    {TemplateBinding Parent.BindingContext.SizeModifier.TestWidth.Value}

    I am not able to use it in columndefinition's width because of https://github.com/xamarin/Xamarin.Forms/issues/4835

  • TrixoTrixo Member ✭✭

    Following works.
    {Binding BindingContext.SizeModifier.TestWidth, Source={x:Reference Self}}

    seems like no need for Parent keyword.

  • Alex0407Alex0407 Member ✭✭

    Dears

    I have more or less the same issue. I am working on some template control currently. It uses Grid to place two labels.

    the code behind is the following

        public static readonly BindableProperty PromptWidthProperty = BindableProperty.Create(
                                                nameof(PromptWidth),
                                                typeof(GridLength),
                                                typeof(TextFieldViewControl),
                                                defaultValue: GridLength.Star);
    
        public GridLength PromptWidth
        {
            get
            {
                return (GridLength)GetValue(PromptWidthProperty);
            }
            set
            {
                SetValue(PromptWidthProperty, value);
            }
        }
    

    XAML code

    <ContentView.ControlTemplate>
        <ControlTemplate>
    
            <Grid Margin="0,0,0,12" 
                    BackgroundColor="{TemplateBinding BackgroundColor}">
    
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="{TemplateBinding PromptWidth}"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
    

    .....

    The following exception is thrown as soon as I enable TemplateBinding for column width. The control works fine without it.
    What can be the issue ?

    Exception has been thrown by the target of an invocation.

    Thank you in advance

  • TrixoTrixo Member ✭✭

    @Alex0407 Have you tried my solution?
    Set parent container's xname to x:Name="Self

    and then just use normal binding with source reference to that element

    {Binding BindingContext.SizeModifier.TestWidth, Source={x:Reference Self}}

  • Alex0407Alex0407 Member ✭✭
    edited April 27

    Hi Trixo

    thank you for your fast feedback.
    I have updated the solution accordingly to your recommendations and it works.

    it was before
    ColumnDefinition Width="{TemplateBinding PromptWidth}"

    it is now
    ColumnDefinition Width="{Binding PromptWidth, Source={x:Reference this}}"

    where "this" is declared as below
    x:Name="this"

    If TemplateBinding is used then the following exception is thrown

    System.InvalidOperationException: 'Operation is not valid due to the current state of the object.'

    Why does TemplateBinding work fine for other bindable properties of the same control ?

    For example, the control has a property declared like this
    <Label Grid.Column="0" Grid.Row="0"
    Text="{TemplateBinding PromptText}"
    Style="{StaticResource TextFieldViewPrompt}"

    and it works fine always.

    What is the possible reason of such difference ? Data type ?

Sign In or Register to comment.