AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.09k stars 2.26k forks source link

{And}, {Or} MultiBinding Markup extensions, supported by XamlX compiler #17621

Open Mikolaytis opened 2 days ago

Mikolaytis commented 2 days ago

Is your feature request related to a problem? Please describe.

To have a nice xaml we use {And} and {Or} markup extensions, that support bindings, etc. Here is an example:

<LazyView IsVisible="{And {Binding SideBar.Illustrations.IsSelected},
                          {Binding !#EyedropperPanel.IsVisible}}"
          Type="Illustrations" />

Also it supports nesting:

IsVisible="{And {Binding SelectedTeam.UserPermissions.ProjectCreate,
                                 FallbackValue={x:False}},
                {Or {Binding SelectedPageIndex,
                                     Converter={x:Static Converters.IsEqual},
                                     ConverterParameter=0},
                    {Binding SelectedTeam.ProjectCollection.Count,
                                     Converter={x:Static Converters.LessOrEqualThan},
                                     ConverterParameter=2,
                                     FallbackValue={x:False}}}}" />

Describe the solution you'd like

I think this should be supported by the compiler, because markup extensions have allocation overhead.

Describe alternatives you've considered

Here is how our And and Or markup extensions look:

public class Or : MarkupExtension
{
    private readonly IBinding[] _bindings;

    public Or(object b1, object b2)
    {
        if (b1 is not IBinding bind1 ||
            b2 is not IBinding bind2)
        {
            throw new BindingChainException("'Or' MarkupExtension binging error");
        }

        _bindings = new[] { bind1, bind2 };
    }

    public Or(object b1, object b2, object b3)
    {
        if (b1 is not IBinding bind1 ||
            b2 is not IBinding bind2 ||
            b3 is not IBinding bind3)
        {
            throw new BindingChainException("'Or' MarkupExtension binging error");
        }

        _bindings = new[] { bind1, bind2, bind3 };
    }

    //here was ctors for 4-7 elements

    public override object ProvideValue(IServiceProvider serviceProvider) => new MultiBinding
    {
        Converter = BoolConverters.Or,
        Bindings = _bindings
    };
}

And looks the same as Or

Additional context

We have 275 multibindings in our codebase. All of them using markup extension style over <multibinding> style for making a markup code smaller, 10x easier to read - and this is a real benefit in a complex markups.

maxkatz6 commented 1 day ago

Consider {Binding And(SideBar.Illustrations.IsSelected, !#EyedropperPanel.IsVisible)} as an alternative syntax proposal. It also has a precedent in XAML: https://learn.microsoft.com/en-us/windows/uwp/data-binding/function-bindings

Mikolaytis commented 1 day ago

Consider {Binding And(SideBar.Illustrations.IsSelected, !#EyedropperPanel.IsVisible)} as an alternative syntax proposal. It also has a precedent in XAML: https://learn.microsoft.com/en-us/windows/uwp/data-binding/function-bindings

my proposal is easier to implement because parsing is not an issue, and already supported by analysis of a rider. also my proposal can combine different types of Bindings... TemplateBinding, maybe x:Static, and Static/DynamicResource...