maui

Selecting an Entry should change the Label's Text but it does not


I have one label and two entries. I want to make the label display the selected entry. Right now selecting the second entry does not change the label. What is the culprit?

Here is my code.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MyProject"
             x:Class="MyProject.TestPage"
             x:DataType="vm:TestViewModel"
             Title="TestPage">
    <VerticalStackLayout>
        <Entry x:Name="Entry1"  Text="Entry 1">
            <Entry.GestureRecognizers>
                <TapGestureRecognizer Command="{Binding SetSelectedEntryCommand}"
                                      CommandParameter="{Reference Entry1}" />
            </Entry.GestureRecognizers>
        </Entry>
        <Entry x:Name="Entry2"
               Text="Entry 2">
            <Entry.GestureRecognizers>
                <TapGestureRecognizer Command="{Binding SetSelectedEntryCommand}"
                                      CommandParameter="{Reference Entry2}" />
            </Entry.GestureRecognizers>
        </Entry>
  
        <Label Text="{Binding SelectedEntry.Text}" />
    </VerticalStackLayout>
</ContentPage>
public partial class TestPage : ContentPage
{
    public TestPage(TestViewModel model)
    {
        InitializeComponent();
        BindingContext = model;
        model.InitializeCommand.Execute(Entry1);
    }
}

It is annoying: It looks like your post is mostly code; please add some more details.

public partial class TestViewModel : ObservableObject
{
    [ObservableProperty]
    Entry _selectedEntry;

    [RelayCommand]
    void Initialize(Entry selectedEntry)
    {
        SelectedEntry = selectedEntry;
        SelectedEntry.BackgroundColor = Colors.Pink;
    }

    [RelayCommand]
    void SetSelectedEntry(Entry selectedEntry)
    {
        SelectedEntry.BackgroundColor = Colors.White;
        SelectedEntry = selectedEntry;
        SelectedEntry.BackgroundColor = Colors.Pink;
    }
}

Edit

Apparently it works on Android but it does NOT work on Windows. Because I need a touch screen on Windows?


Solution

  • A variation @FreakyAli's answer, you can bind to the IsFocused property and use it in a DataTrigger as follows. This would minimize the amount of work your View Model needs to do since you can implement all the requirements in the View only, e.g.

    <VerticalStackLayout Padding="30,0" Spacing="25">
        <Entry x:Name="Entry1" Text="Entry 1" />
        <Entry x:Name="Entry2" Text="Entry 2" />
        <Label x:DataType="Entry" Text="{Binding Text, Source={Reference Entry1}}">
            <Label.Triggers>
                <DataTrigger
                    x:DataType="Entry"
                    Binding="{Binding IsFocused, Source={Reference Entry2}}"
                    TargetType="Label"
                    Value="True">
                    <Setter x:DataType="Entry" Property="Text" Value="{Binding Text, Source={Reference Entry2}}" />
                </DataTrigger>
            </Label.Triggers>
        </Label>
    </VerticalStackLayout>
    

    I do have a CommunityToolkit MultiMathExpressionConverter enhancement that has a simple XAML solution that helps solve your problem at increasing scale, e.g. for 3 Entry fields:

    <VerticalStackLayout Padding="30,0" Spacing="25">
        <Entry x:Name="Entry1" Text="Entry 1" />
        <Entry x:Name="Entry2" Text="Entry 2" />
        <Entry x:Name="Entry3" Text="Entry 3" />
        <Label Text="{MultiBinding {Binding Text, Source={Reference Entry1}},
                                   {Binding IsFocused, Source={Reference Entry2}},
                                   {Binding Text, Source={Reference Entry2}},
                                   {Binding IsFocused,Source={Reference Entry3}},
                                   {Binding Text, Source={Reference Entry3}},
                                   Converter={StaticResource MultiMathExpressionConverter},
                                   ConverterParameter='x1 and x2 or x2 and x3 or x0'}" />
    </VerticalStackLayout>
    

    The above is based on being able to write the Label.Text expression as:

    Label.Text = Entry2.IsFocused && Entry2.Text
              || Entry3.IsFocused && Entry3.Text
              || Entry1.Text
    

    Or you could do something more conventional such as ConverterParameter='x1 ? x2 : x3 ? x4 : x0' which means:

     Label.Text = Entry2.IsFocused
                   ? Entry2.Text
                   : Entry3.IsFocused
                     ? Entry3.Text
                     : Entry1.Text
    

    Help me out by voting on it: