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.

What technique is best for multiple Entries evaluating each other's values?

Hello, if I were to want 3 entries that all measured the same object differently, as in "Weight, Volume, Count," what technique should I look into to allow a user to enter into any of the three, and the other 2 update? Like, if I enter a Weight, the Volume and Count adjust, or you could enter a Count which recalculates the other values. The objects are being displayed in a CollectionView with a DataTemplate.

Initially, I called methods in property setters... but it causes an infinite loop. Is Multi-Binding relevant? I didn't really get the gist of what that meant. I'd be glad to share a test project if I got a tip on which way to begin it.

Thanks!

Best Answer

Answers

  • stXamDevstXamDev Member ✭✭✭
    edited October 17

    Each entry has a text changed event , capture that and accordingly change the text of the other two entries.

    View

    <StackLayout BackgroundColor="White" Padding="20,10,20,10">
                <StackLayout Orientation="Horizontal">
                    <Label Text="Entry One(x)" VerticalOptions="Center"/>
                    <Entry x:Name="XEntry" HorizontalOptions="FillAndExpand" TextChanged="Entry_TextChanged"/>
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                    <Label Text="Entry Two(x square)" VerticalOptions="Center"/>
                    <Entry x:Name="XSquareEntry" HorizontalOptions="FillAndExpand" TextChanged="Entry_TextChangedSquare"/>
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                    <Label Text="Entry three(x cube)" VerticalOptions="Center"/>
                    <Entry x:Name="XCubeEntry" HorizontalOptions="FillAndExpand" TextChanged="Entry_TextChangedCube"/>
                </StackLayout>
            </StackLayout>
    

    CodeBehind

    private void Entry_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (sender is Entry entry && entry.IsFocused)
                {
                    if (double.TryParse(e.NewTextValue, out double number))
                    {
                        XSquareEntry.Text = (number * number).ToString();
                        XCubeEntry.Text = (number * number * number).ToString();
                    }
                    else
                    {
                        DisplayAlert("Alert", "Enter numeric val", "ok");
                    }
                }
            }
    
            private void Entry_TextChangedSquare(object sender, TextChangedEventArgs e)
            {
                if (sender is Entry entry && entry.IsFocused)
                {
                    if (double.TryParse(e.NewTextValue, out double numberSquare))
                    {
                        double number = Math.Sqrt(numberSquare);
                        XEntry.Text = number.ToString();
                        XCubeEntry.Text = (number * number * number).ToString();
                    }
                    else
                    {
                        DisplayAlert("Alert", "Enter numeric val", "ok");
                    }
                }
            }
    
            private void Entry_TextChangedCube(object sender, TextChangedEventArgs e)
            {
                if (sender is Entry entry && entry.IsFocused)
                {
                    if (double.TryParse(e.NewTextValue, out double numberCube))
                    {
                        double number = Math.Ceiling(Math.Pow(numberCube, (double)1 / 3)); ;
                        XEntry.Text = number.ToString();
                        XSquareEntry.Text = (number * number).ToString();
                    }
                    else
                    {
                        DisplayAlert("Alert", "Enter numeric val", "ok");
                    }
                }
            }
    

    Demo

  • ScumSprocketScumSprocket Member ✭✭

    Thanks I have been fighting some other buggy stuff, but I can't wait to try these out!

  • ScumSprocketScumSprocket Member ✭✭

    I think I'm going for the model code, because all my entries are in DataTemplates, so code-behind doesn't know where these entries are... is there a way to let the code-behind know?

  • jezhjezh Member, Xamarin Team Xamurai

    is there a way to let the code-behind know?

    You can try to use Data Binding to achieve this.

    1.Create a viewmode (e.g. TestModel.cs)

        public class TestModel : INotifyPropertyChanged
        {
            string _entry1Word;
    
            public string Entry1Word
            {
                set { 
                    SetProperty(ref _entry1Word, value);
    
                    try
                    {
                        Entry2Word = (float.Parse(_entry1Word.ToString()) * 2).ToString();
                        Entry3Word = (float.Parse(_entry1Word.ToString()) * 3).ToString();
                    }
                    catch (Exception e)
                    {
                    }
                    finally {
                    }
    
                }
    
                get { return _entry1Word; }
            }
    
    
            string _entry2Word;
    
            public string Entry2Word
            {
                set { 
                    SetProperty(ref _entry2Word, value);
                }
    
                get { return _entry2Word; }
            }
    
            string _entry3Word;
    
            public string Entry3Word
            {
                set { 
                    SetProperty(ref _entry3Word, value);
                }
    
                get { return _entry3Word; }
            }
    
            public TestModel()
            {
                Entry1Word = "1";
                Entry2Word = "2";
                Entry3Word = "3";
            }
    
            bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
            {
                if (Object.Equals(storage, value))
                    return false;
    
                storage = value;
                OnPropertyChanged(propertyName);
                return true;
            }
    
            protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    

    Note:When you change the first entry's value(Entry1Word), you can also change the binded value of other two entries.
    Of course, you can also change other two binded value like this.

            public string Entry1Word
            {
                set { 
                    SetProperty(ref _entry1Word, value);
    
                    try
                    {
                        Entry2Word = (float.Parse(_entry1Word.ToString()) * 2).ToString();
                        Entry3Word = (float.Parse(_entry1Word.ToString()) * 3).ToString();
                    }
                    catch (Exception e)
                    {
                    }
                    finally {
                    }
                }
                get { return _entry1Word; }
            }
    

    2.Usage sample:

    <?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:multipleapp1="clr-namespace:MultipleApp1"
                 x:Class="MultipleApp1.MainPage">
    
    
        <ContentPage.BindingContext>
            <multipleapp1:TestModel>
            </multipleapp1:TestModel>
        </ContentPage.BindingContext>
    
        <StackLayout BackgroundColor="White" Padding="20,10,20,10">
            <StackLayout Orientation="Horizontal">
                <Label Text="Entry One(x)" VerticalOptions="Center"/>
                <Entry x:Name="XEntry" HorizontalOptions="FillAndExpand" Text="{Binding Entry1Word}" />
            </StackLayout>
            <StackLayout Orientation="Horizontal">
                <Label Text="Entry Two(x square)" VerticalOptions="Center"/>
                <Entry x:Name="XSquareEntry" HorizontalOptions="FillAndExpand"  Text="{Binding Entry2Word}"/>
            </StackLayout>
            <StackLayout Orientation="Horizontal">
                <Label Text="Entry three(x cube)" VerticalOptions="Center"/>
                <Entry x:Name="XCubeEntry" HorizontalOptions="FillAndExpand" Text="{Binding Entry3Word}"/>
            </StackLayout>
        </StackLayout>
    
    </ContentPage>
    
  • ScumSprocketScumSprocket Member ✭✭

    Thanks! I went for altering the model because I haven't found much documentation on how DataTemplates implement events.

Sign In or Register to comment.