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.

Change binding based on switch IsToggled property

Hello guys

I'm currently using a switch to hide/show a layout containing four entry boxes. The boxes are used to calculate a value. If the switch os toggled off, the value is a manual input where I use binding to save to database.

I would then like to change the binding to the combined value of the four entryboxes, but I can't find out how.

Can someone point me in the right direction?

My current XAML looks like this (It's the mValue1, mLampda1, mValue2 and mLampda2 values that I calculate from, and I want to populate the UValue entry with the data.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="LommeKonstruktoren.Views.NewItemPage" Shell.PresentationMode="ModalAnimated" Title="New Item">
    <ContentPage.Content>
        <ScrollView>
            <StackLayout Spacing="2" Padding="15, 35">

                <Label Text="Navn:" FontSize="Medium" />
                <Entry Text="{Binding Name, Mode=TwoWay}" FontSize="Medium" />
                <Label Text="Varmeledningsevne λ:" FontSize="Medium" />
                <Entry Text="{Binding UValue, Mode=TwoWay}" FontSize="Medium" Keyboard="Numeric"/>
                <Grid Margin="0,10,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="2*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Label Text="Inhomogent materialelag:" Grid.Column="0" Grid.Row="0" FontAttributes="Bold" VerticalOptions="Center"/>
                    <Switch x:Name="InhomogentSwitch" Grid.Column="1" Grid.Row="0" HorizontalOptions="End" VerticalOptions="Center" IsToggled="{Binding IsInhomogent}"/>
                </Grid>
                 <StackLayout x:Name="InhomogentStackLayout" IsVisible="{Binding IsInhomogent}">
                     <BoxView HeightRequest="1" Color="Silver" HorizontalOptions="Fill" Margin="0,10,0,0"/>
                    <Label Text="Udregn λ for inhomogent materialelag"
                           FontSize="17" FontAttributes='Bold'
                           HorizontalTextAlignment="Center"
                           Padding="0,5,0,10"/>

                    <StackLayout x:Name="Materiale1StackLayout" Padding="0,0,0,10" Spacing="5">
                    <Label Text="Materiale 1" FontSize="18" FontAttributes="Bold" />

                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="1*" />
                            </Grid.ColumnDefinitions>
                            <Label Text="Bredde [mm]:" FontSize="15" VerticalOptions="Center" Grid.Column="0" />
                            <Entry x:Name="mBredde1" Placeholder="Eks.: 290" Keyboard="Numeric" Grid.Column="1" Text="{Binding mValue1}" />
                        </Grid>

                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="1*" />
                            </Grid.ColumnDefinitions>
                            <Label Text="Lampda-værdi [W/mK]:" FontSize="15" VerticalOptions="Center" Grid.Column="0"/>
                            <Entry x:Name="mLampda1" Placeholder="Eks.: 0,037" Keyboard="Numeric" Grid.Column="1" Text="{Binding mLampda1}"/>
                        </Grid>
                    </StackLayout>

                    <StackLayout x:Name="Materiale2StackLayout">
                    <Label Text="Materiale 2" FontSize="18" FontAttributes="Bold" />

                        <Grid>
                        <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="1*" />
                        </Grid.ColumnDefinitions>
                            <Label Text="Bredde [mm]:" FontSize="15" VerticalOptions="Center" Grid.Column="0" />
                            <Entry x:Name="mBredde2" Placeholder="Eks.: 710" Keyboard="Numeric" Grid.Column="1" Text="{Binding mValue2}"/>
                        </Grid>

                        <Grid>
                        <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="1*" />
                        </Grid.ColumnDefinitions>
                            <Label Text="Lampda-værdi [W/mK]:" FontSize="15" VerticalOptions="Center" Grid.Column="0" />
                            <Entry x:Name="mLampda2" Placeholder="Eks.: 0,037" Keyboard="Numeric" Grid.Column="1" Text="{Binding mLampda2}"/>
                        </Grid>
                    </StackLayout>
                    <BoxView HeightRequest="1" Color="Silver" HorizontalOptions="Fill" />
                </StackLayout>


                <Label Text="Description:" FontSize="Medium" />
                <Editor Text="{Binding Description, Mode=TwoWay}" AutoSize="TextChanges" FontSize="Medium" Margin="0" />
                <StackLayout Orientation="Horizontal">
                        <Button Text="Cancel" Command="{Binding CancelCommand}" HorizontalOptions="FillAndExpand" />

                        <Button Text="Save" Command="{Binding SaveCommand}" HorizontalOptions="FillAndExpand" />

                </StackLayout>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

And the ViewModel looks like this:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using LommeKonstruktoren.Models;
using Xamarin.Forms;

namespace LommeKonstruktoren.ViewModels
{
    public class NewItemViewModel : BaseViewModel
    {
        private string name;
        private string uvalue;
        private string description;
        private bool isinhomogent;
        private double mvalue1;
        private double mlampda1;
        private double mvalue2;
        private double mlampda2;

        public NewItemViewModel()
        {
            SaveCommand = new Command(OnSave, ValidateSave);
            CancelCommand = new Command(OnCancel);
            this.PropertyChanged +=
                (_, __) => SaveCommand.ChangeCanExecute();
        }

        private bool ValidateSave()
        {
            return !String.IsNullOrWhiteSpace(name)
                && !String.IsNullOrWhiteSpace(uvalue);
        }

        public string Name
        {
            get => name;
            set => SetProperty(ref name, value);
        }

        public string UValue
        {
            get => uvalue;
            set => SetProperty(ref uvalue, value);
        }

        public bool IsInhomogent
        {
            get => isinhomogent;
            set => SetProperty(ref isinhomogent, value);
        }

        public double mValue1
        {
            get => mvalue1;
            set => SetProperty(ref mvalue1, value);
        }

        public double mValue2
        {
            get => mvalue2;
            set => SetProperty(ref mvalue2, value);
        }

        public double mLampda1
        {
            get => mlampda1;
            set => SetProperty(ref mlampda1, value);
        }


        public double mLampda2
        {
            get => mlampda2;
            set => SetProperty(ref mlampda2, value);
        }

        public string Description
        {
            get => description;
            set => SetProperty(ref description, value);
        }

        public Command SaveCommand { get; }
        public Command CancelCommand { get; }

        private async void OnCancel()
        {
            // This will pop the current page off the navigation stack
            await Shell.Current.GoToAsync("..");
        }

        private async void OnSave()
        {
            Item newItem = new Item()
            {
                Id = Guid.NewGuid().ToString(),
                Name = Name,
                UValue = UValue,
                Description = Description,
                IsInhomogent = IsInhomogent,
                mValue1 = mValue1,
                mLampda1 = mlampda1,
                mValue2 = mValue2,
                mLampda2 = mlampda2
            };

            await DataStore.AddItemAsync(newItem);

            // This will pop the current page off the navigation stack
            await Shell.Current.GoToAsync("..");
        }
    }
}

Best Answer

Answers

  • XamDevSTXamDevST Member ✭✭

    @mndevelopments simplify your use case, There are 4 entry and these are binded to 4 different properties , are you saying when these entries are not visible you want to bind 5th entry with total of the 4 properties?

  • mndevelopmentsmndevelopments Member ✭✭
    edited October 24

    @XamDevST
    I'll will try to simplify it - my bad.

    I got an entry lets call it TotalValue, that the user inputs and saves with a Name value when the "IsVisible" switch is off.
    Above is done with {Binding TotalValue} to the entry field. TotalValue is then saved to a table in Sqlite or Azure database.

    When the switch is on however, I want the the TotalValue field to be {Binding CalculatedTotalValue} instead. I can calculate the value in the database with

    public double CalculatedTotalValue 
    {
        get { (mValue1 * mLampda1) + (mValue2 * mLampda2);
    }
    

    Really simplified:
    When switch is off bind to input 1
    When switch is on bind to input 2

    Here is some pictures of my app to show how it all connects.

    Is this doable?

    Hopes above makes sense

  • JarvanJarvan Member, Xamarin Team Xamurai
    edited October 26

    As XamDevST said, try using Triggers to achieve the function. Triggers allow you to express actions declaratively in XAML that change the appearance of controls based on events or property changes. You could detect the value of the IsToggled property.

    Check the code:

    <Switch x:Name="switch"/>
    <Label Text="testing" TextColor="LightBlue">
        <Label.Triggers>
            <DataTrigger TargetType="Label" 
                         Binding="{Binding Source={x:Reference switch},Path=IsToggled}" 
                         Value="false">
                <Setter Property="TextColor" Value="LightPink"/>
            </DataTrigger>
        </Label.Triggers>
    </Label>
    

    Tutorial:
    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/triggers#data-triggers

  • mndevelopmentsmndevelopments Member ✭✭

    @XamDevST and @Jarvan
    Thank you for your input, both of you.

    Sorry for the "late" reply. I've been busy with other projects the last couple of days.

    The triggers worked perfectly, however I'm having trouble getting the data variables to update when I use the triggers.

    How would I make the calculation happen when the event is triggered?

  • XamDevSTXamDevST Member ✭✭
    edited October 26

    @mndevelopments again simplify your use case and post another question.
    Do you mean the PropertyTwo is not getting updated? if so try mode=twoway

    <Setter Property="Text" Value="{Binding PropertyTwo,Mode="TwoWay"}"/>
    
  • mndevelopmentsmndevelopments Member ✭✭

    @XamDevST
    I will do som testing, and post another question instead, if I can't find a solution.

    Thank you for the help.

Sign In or Register to comment.