dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.02k stars 1.73k forks source link

Button wont get disabled at startup #20347

Open ShariatPanah opened 7 months ago

ShariatPanah commented 7 months ago

Description

i'm trying to disable a button based on an Entry's Text.Length but it won't get disabled at startup when the entry is empty, but then when i type in the entry and clear it out, the button gets disabled, i tried using DataTriggers and also binding the Button.IsEnabled to Text.Length using a converter but none of them work at startup

Steps to Reproduce

either use this:

<Button
    Command="{Binding AddSectionCommand}"
    CommandParameter="{Binding Section}"
    IsEnabled="{Binding Source={x:Reference txtTitle}, Path=Text.Length, Converter={StaticResource lengthConverter}}"
    Text="Save"/>

or this:

<Button
    Command="{Binding AddSectionCommand}"
    CommandParameter="{Binding Section}"
    Text="Save">
    <Button.Triggers>
        <DataTrigger
            Binding="{Binding Source={x:Reference txtTitle}, Path=Text.Length}"
            TargetType="Button"
            Value="0">
            <Setter Property="IsEnabled" Value="False" />
        </DataTrigger>
    </Button.Triggers>
</Button>

Link to public reproduction project repository

No response

Version with bug

8.0.6

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 12.0

Did you find any workaround?

No response

Relevant log output

No response

ghost commented 7 months ago

Hi @ShariatPanah. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ShariatPanah commented 7 months ago

here is the repro link: https://github.com/ShariatPanah/ButtonDisableBug

ShariatPanah commented 7 months ago

And as i mentioned before, it doesn't matter if you bind the IsEnabled property to the text.length using a converter or you use DataTrigger, it won't disable the button at startup when the entry is empty

jenscski commented 7 months ago

Not sure if this can be considered a bug or not, but the issues is that Entry.Text is default NULL, so the trigger that checks for Text.Length=0 will not succeed, because Text is NULL.

If you explicit set the Entry.Text to an empty string, then it works as excepted.

<Entry x:Name="txtTitle" Text="" />

ShariatPanah commented 7 months ago

@jenscski you are right, but as i said even with a converter it won't work, the converter won't even get called at startup, I'm binding the entry to a property of an object, at first this string property is null, but doesn't it have to call the converter at any time? like to evaluate and render the View? i don't know maybe this behavior is by design. please let me know

jenscski commented 7 months ago

What is the lengthConverter ?

Have you looked at .NET MAUI Community Toolkit, and their converters? E.g. https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/converters/is-string-not-null-or-empty-converter

ShariatPanah commented 7 months ago

@jenscski the lengthConverter is a resource i added to ContentPage.Resources and gave it this name as x:Key, it's of my TextLengthToBoolConverter Class type, here is the code:

public class TextLengthToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return false;

        if ((int)value == 0)
            return false;

        return true;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

i can use this converter to check if the entry text property is null or empty or is filled. and based on this the button's IsEnabled property is being set. it does work after i type some character into the entry and clear it, but at startup this converter won't even get called,

ShariatPanah commented 7 months ago

i updated my repo and added converter to reproduce the issue, here is the link: https://github.com/ShariatPanah/ButtonDisableBug

jenscski commented 7 months ago

When you are using a backing field to bind to, you should also use this field to check for changes.

 <Button
     HorizontalOptions="Fill"
     IsEnabled="{Binding Title, Converter={StaticResource lengthConverter}}"
     Text="Click me">
 </Button>
ShariatPanah commented 7 months ago

When you are using a backing field to bind to, you should also use this field to check for changes.

I'm sorry i didn't get your point. Yes i am binding IsEnabled to Entry's Text using converter, i did everything right please take a look at my repo

jenscski commented 7 months ago

You need to bind to the bindingcontext's Title, not the entry's text.

jenscski commented 7 months ago

I created a pull request for you, that show how to do this using MVVM and converters.

https://github.com/ShariatPanah/ButtonDisableBug/pull/1

ShariatPanah commented 7 months ago

I created a pull request for you, that show how to do this using MVVM and converters.

I'll give it a try and will let you know the result, thanks.