Binding horizontal and vertical options don't work properly

rbiezerbieze Member ✭✭

I'm trying to reposition some text labels by changing the horizontal and vertical options in a viewmodel, however, when i update the horizontal and vertical options my label moves to the top left corner instead of the correct position, when i update the text in the label the correct position will be set. is it possible to instantly set the correct new position instead of the label moving to the top left corner first?

` the goal is to reposition the label inside of the frame by selecting a new position from a picker

            <Frame Grid.Row="0" 
                   Grid.Column="0"
                   BorderColor="Black"
                   Margin="10">
                <Label Text="{Binding PreviewCellText}"
                       HorizontalOptions="{Binding HorizontalOption}"
                       VerticalOptions="{Binding VerticalOption}"
                       >
                </Label>
            </Frame>

`

Horizontal and vertical property's in viewmodel:
` private LayoutOptions horizontalOption;

    public LayoutOptions HorizontalOption
    {
        get => horizontalOption;
        set
        {
            horizontalOption = value;
            OnPropertyChanged(nameof(HorizontalOption));
        }
    }

    private LayoutOptions verticalOption;

    public LayoutOptions VerticalOption
    {
        get => verticalOption;
        set
        {
            verticalOption = value;
            OnPropertyChanged(nameof(VerticalOption));
        }
    }

`

picker property

` private string selectedPosition;

    public string SelectedPosition
    {
        get => selectedPosition;
        set
        {
            selectedPosition = value;
            UpdateLocation(value);
        }
    }

`

` UpdateLocation method:

    private void UpdateLocation(string selectedPosition)
    {
        Debug.WriteLine("Can update location: " + selectedPosition);
        switch (selectedPosition)
        {
            case "Gecentreerd":
                HorizontalOption = LayoutOptions.Center;
                VerticalOption = LayoutOptions.Center;
                break;
        ...
        }
    }

`
aparently i cant upload any images to show what i want to achieve...

Best Answer

  • rbiezerbieze ✭✭
    Accepted Answer

    @JohnHardman i've tested this implementation on WPF and Android too, and this works just fine. on UWP it doesnt work so i guess its a UWP bug

Answers

  • JohnHardmanJohnHardman GBUniversity mod

    @rbieze

    It's not something I've ever tried, but it sounds like a bug. Before logging it, I recommend checking what happens if you haven't got everything nested in a Grid. If, after doing that, it still looks like a bug, I suggest logging it over at Github Issues.

    Having said that, I'd advise against having the View Model know about your View. In a purist MVVM world, a View Model shouldn't know about positioning of elements on a page. If the position change reflects some status change, have the View Model expose the status through a property, then have ValueConverters in your View change the status to the LayoutOption required.

  • rbiezerbieze Member ✭✭

    @JohnHardman thanks for your replie, ill try what you said. I've also tried using a value converter, but it doesnt help the issue.

  • rbiezerbieze Member ✭✭

    @JohnHardman i've created the simplest version of what you said and that only seems to work with only one value change, when i change it again the label gets positioned at the top left corner again.

  • rbiezerbieze Member ✭✭

    here's a screenshot of the application: so, when i select an item from the picker it should instantly change the position of the label

    here's the current situation:

    here's the expected situation (i edited the gif in order to show the expected outcome)

  • JohnHardmanJohnHardman GBUniversity mod

    @rbieze said:
    @JohnHardman i've created the simplest version of what you said and that only seems to work with only one value change, when i change it again the label gets positioned at the top left corner again.

    Post the code for that version. I'll take a look later on when I get time (will be busy for next 2-3 hours at least)

  • rbiezerbieze Member ✭✭

    @JohnHardman

    viewModel:

    `using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Text;
    using Xamarin.Forms;

    namespace Prototype.CustomComponents.RepositionPrototype
    {
    public class RepositionPrototypeViewModel : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;
    public Command ClickedDebugCommand { get; set; }
    private string cellText;

        public string CellText
        {
            get => cellText;
            set
            {
                cellText = value;
                OnPropertyChanged(nameof(CellText));
            }
        }
    
        private string horizontalOption;
    
        public string HorizontalOption
        {
            get => horizontalOption;
            set
            {
                horizontalOption = value;
                OnPropertyChanged(nameof(HorizontalOption));
            }
        }
    
        private string verticalOption;
    
        public string VerticalOption
        {
            get => verticalOption;
            set
            {
                verticalOption = value;
                OnPropertyChanged(nameof(VerticalOption));
            }
        }
    
        private string selectedPosition;
    
        public string SelectedPosition
        {
            get => selectedPosition;
            set
            {
                selectedPosition = value;
                OnPropertyChanged(nameof(SelectedPosition));
                UpdatePosition(value);
            }
        }
    
        public RepositionPrototypeViewModel()
        {
            ClickedDebugCommand = new Command(()=> ClickedDebug());
            CellText = "Test";
        }
    
        private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(name));
        }
    
        private void UpdatePosition(string value)
        {
            Debug.WriteLine("updating position: " + value);
            if (value == "Middle Right")
            {
                Debug.WriteLine("value Middle Right detected...");
                VerticalOption = "Center";
                HorizontalOption = "End";
            }
            else if (value == "Top Right")
            {
                Debug.WriteLine("value Top Right detected...");
                VerticalOption = "Start";
                HorizontalOption = "End";
            }
            CellText = "Picker";
        }
    
        private void ClickedDebug()
        {
            CellText = "New Message:";
            VerticalOption = "Start";
            HorizontalOption = "Start";
            Debug.WriteLine("Clicked Debug...");
        }
    }
    

    }`

    converter:
    `using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.Text;
    using Xamarin.Forms;

    namespace Prototype.Converters.StringToLayoutOptionConverter
    {
    class StringToLayoutOptionConverter : IValueConverter
    {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
    Debug.WriteLine("converter value: " + value);
    var val = (string) value;

            if (val == "Start")
            {
                Debug.WriteLine("value in if:" + val);
                return LayoutOptions.Start;
            }
            else if (val == "End")
            {
                Debug.WriteLine("value in if:" + val);
                return LayoutOptions.End;
            }
            else if (val == "Center")
            {
                Debug.WriteLine("value in if:" + val);
                return LayoutOptions.Center;
            }
            else
            {
                Debug.WriteLine("value in else:" + val);
                return LayoutOptions.Fill;
            }
    
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    }
    `

    xaml page:

    `
    <?xml version="1.0" encoding="utf-8" ?>

    <ContentPage.Resources>
        <ResourceDictionary>
            <converter:StringToLayoutOptionConverter x:Key="stringToLayoutOptionConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>
        <StackLayout>
            <Frame BorderColor="Black"
                   Margin="10"
                   VerticalOptions="FillAndExpand"
                   HorizontalOptions="FillAndExpand">
                <Label Text="{Binding CellText}"
                       HorizontalOptions="{Binding HorizontalOption, Converter={StaticResource stringToLayoutOptionConverter}}"
                       VerticalOptions="{Binding VerticalOption, Converter={StaticResource stringToLayoutOptionConverter}}">
                </Label>
            </Frame>
            <Picker SelectedItem ="{Binding SelectedPosition}"
            >
                <Picker.Items>
                    <x:String>Middle Right</x:String>
                    <x:String>Top Right</x:String>
                    <x:String>Bottom Right</x:String>
                    <x:String>Middle Left</x:String>
                    <x:String>Top Left</x:String>
                    <x:String>Bottom Left</x:String>
                    <x:String>Top Center</x:String>
                    <x:String>Bottom Center</x:String>
                    <x:String>Center</x:String>
                </Picker.Items>
            </Picker>
    
        </StackLayout>
    </ContentPage.Content>
    

    `

  • rbiezerbieze Member ✭✭
    Accepted Answer

    @JohnHardman i've tested this implementation on WPF and Android too, and this works just fine. on UWP it doesnt work so i guess its a UWP bug

  • JohnHardmanJohnHardman GBUniversity mod

    @rbieze said:
    @JohnHardman i've tested this implementation on WPF and Android too, and this works just fine. on UWP it doesnt work so i guess its a UWP bug

    Good investigatory work :-) Can you log it in Github Issues please.

  • rbiezerbieze Member ✭✭

    @JohnHardman created an issue on Github :smile:

Sign In or Register to comment.