Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IsNullOrEmptyStateTrigger on SelectedItem #4426

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

XAML-Knight
Copy link
Contributor

Fixes #4411

PR Type

What kind of change does this PR introduce?

Bugfix

What is the current behavior?

The IsNullOrEmptyStateTrigger did not fire correctly when placed on the SelectedItem of a typical items control (i.e., ListBox, ListView, etc). The default value of it's Value dependency property (which is of type object) was set to true, not null. The logic behind the trigger is inspecting for null or empty, and the bool value true is neither of these.

What is the new behavior?

The default value of the trigger's Value dependency property is now set to null. A boolean dependency property (IsActive) was added, in order to set the initial state of the trigger directly in the XAML.

A new section was added to the IsNullOrEmptyStateTrigger Sample Page, highlighting the behavior of the trigger when placed on a SelectedItem property.

image

PR Checklist

Please check if your PR fulfills the following requirements:

  • Tested code with current supported SDKs
  • New component
    • Pull Request has been submitted to the documentation repository instructions. Link:
    • Added description of major feature to project description for NuGet package (4000 total character limit, so don't push entire description over that)
    • If control, added to Visual Studio Design project
  • Sample in sample app has been added / updated (for bug fixes / features)
  • New major technical changes in the toolkit have or will be added to the Wiki e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Header has been added to all new source files (run build/UpdateHeaders.bat)
  • Contains NO breaking changes

Other information

@ghost
Copy link

ghost commented Dec 14, 2021

Thanks XAML-Knight for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request 🙌

@ghost ghost requested a review from azchohfi December 14, 2021 19:40
@ghost ghost added the bug 🐛 An unexpected issue that highlights incorrect behavior label Dec 14, 2021
@michael-hawker
Copy link
Member

@dotMorten did you want to help review this PR? Thanks!

Copy link
Contributor

@dotMorten dotMorten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default value the Value property in this trigger is null, I'm betting when you start with a binding that evaluates to null, it never actually calls SetActive(true); Instead I think the constructor of the trigger just needs to call SetActive(true), so its initial state matches the Value property

Comment on lines 34 to 57
/// <summary>
/// Gets or sets a value indicating whether a trigger is active.
/// </summary>
public bool IsActive
{
get => (bool)GetValue(IsActiveProperty);
set => SetValue(IsActiveProperty, value);
}

/// <summary>
/// Identifies the <see cref="IsActive"/> DependencyProperty
/// Allows user to enable the trigger from XAML
/// </summary>
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(IsNullOrEmptyStateTrigger), new PropertyMetadata(false, OnIsActiveChanged));

private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null && e.NewValue is bool)
{
var obj = (IsNullOrEmptyStateTrigger)d;
obj.SetActive((bool)e.NewValue);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

State triggers doesn't use public IsActive properties, but just the base SetActive method.. It's not clear what purpose this one serves? It seems like you can activate this trigger by either setting it to true or the Value to not-null? Which one takes precedence?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When putting in the fix for this issue (#4411), the fix worked except for the initial load of the control/sample page. It's as if the trigger wasn't being evaluated at load time. Hence, the need to at least initially set the trigger to be active. Another hack would have been to just assign Sting.Empty to the SelectedItem in the constructor of the page's code-behind, but I didn't like that approach, and implemented the bool DP instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default value is null, it means it is active at creation, so you should call SetActive(true) in the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default value is null, it means it is active at creation

This logic holds, until it doesn't (trigger is not turning On, as expected), which is a condition that was discovered as part of this PR (see the issue with SelectedItem, as mentioned above).

However, by calling SetActive(true) in the constructor of the trigger, as suggested, you'd then be giving this trigger an artificial value ("On") by default. What if a developer does not want the trigger to be on by default? (The logic in the trigger may just wind up overwriting this any way, or it may not.) You'd then be requiring the developer to find a way to turn the trigger off (or, at least, there would be ambiguity as far as if they would have to shut it off, or not).

Contrast that whole approach, by just simply giving our developers an easy way to set an initial state for the trigger, by exposing a boolean property. I've gone a little further, and exposed this boolean as a dependency property, which allows for easy setting of the property in the XAML.

Another approach was the hack (again, mentioned above), of just setting SelectedItem to String.Empty in the Sample Page's code-behind- same result (trigger is now turning On initially), but clearly a hack.

Copy link
Contributor

@dotMorten dotMorten Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, by calling SetActive(true) in the constructor of the trigger, as suggested, you'd then be giving this trigger an artificial value ("On") by default.

How is that artificial? The Value property is null, which means the trigger should be on, until the Value property changes to something not-null.

What if a developer does not want the trigger to be on by default?

Then don't set Value to null or don't set a trigger on it? I don't understand the use-case here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the problem is that we don't have an analogous IsNotNullOrEmptyStateTrigger like we do with Equal/NotEqual?

In the case this trigger is being used, it should be bound to and either that binding is invalid (which is effectively null) or evaluates to some value. The default state of the trigger being on shouldn't be a problem here between the time the trigger is instantiated, the value property is resolved via binding, and the UI is actually displayed.

@ghost
Copy link

ghost commented Dec 21, 2021

This PR has been marked as "needs attention 👋" and awaiting a response from the team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 An unexpected issue that highlights incorrect behavior needs attention 👋
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IsNullOrEmptyStateTrigger not working for ListView
4 participants