-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Conditional XAML #1434
Comments
I think this can be achieved easily by binding to |
Changing Visibility to collapsed or hidden only hides the control so a user does not see it, but it doesn't detach it from visual tree, so images will continue loading in background and controls will get eagerly initialized. |
Interesting. I've never needed such a thing, perhaps because I tend to use MVVM, so if images are disabled then that would be done at the ViewModel level. I'm not sure if this would be a common enough case to include the control in the core library. Do you have any more examples? |
I think that something like that could be naturally achieved using |
But how to implement this using MVVM? As for now, I read settings using Load command and expose a property named ImagesEnabled from my ViewModel — so the UI knows if images are disabled and can easily detach unnecessary controls off using such conditional XAML control. Are there any other ways of doing this? I thought of spoiling image urls — but this is a dirty solution. Another way is to write a custom control inherited from Image that won't load content until a special flag is set — but this solution is not universal — what if I need square images, round images, triangle images (Illuminati will appreciate), or videos. Creating content controls with several
Frankly speaking, I could hardly imagine any other cases where conditional XAML will be the only way to go, so including this feature in the core library may not be really necessary @grokys! But in the future, it can potentially simplify one's codebase. :) |
Note: First let me say that I've never run into this particular case so I could be missing something! Ok, so the way I would do it would just be to expose a And note that if you were to use an If you have other examples though, please let me know! |
UWP has build in x:DeferLoadStrategy attribute for lazy loading and x:Load attribute (Creators Update+) for loading and unloading with binding, which can replace UwpIf/AvaloniaIf <Grid>
<Image x:Name="MyImage"
x:DeferLoadStrategy="Lazy"
Source="{Binding Image, Mode=OneTime}"
Visibility="Collapsed"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<StateTrigger IsActive="{Binding ShouldLoad, Mode=OneWay}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MyImage.Visibility"
Value="Visible"/>
</VisualState.Setters>
</VisualState>
</VisualStateManager.VisualStateGroups>
</Grid> Or <Image x:Load="{Binding ShouldLoad, Mode=OneWay}"
Source="{Binding Image, Mode=OneTime}"/> |
Also UWP has Conditional XAML using namespaces. But it seems to solve other problems. |
Conditional XAML is a much wider topic necessary for XAML re-use between frameworks. I definitely agree that the UWP conditional XAML approach should be used in Avalonia. It was also adopted by Uno and allows platform-specific controls and UI. |
Latest master supports OnPlatform extension (works similarly to MAUI one, but completely compiled). |
@maxkatz6 I'm not sure OnPlatform can actually be used to swap out controls on different platforms? Seems to be fine to do something really simple like change colors but to use it to control the visual tree it seems inadequate. Does Avalonia XAML allow something like switching between a DataGrid and ListBox based on macOS or Android? |
@robloo, yes, it does.
It will be translated into IL code like: This, or users can use OnFormFactor which has Mobile or Default options, which is closer to what you asked. |
It also works with resource dictionaries, generics, I will write a documentation about it closer to release. |
I see, thanks for the details. I was looking at Maui and it looks like it has a bit nicer syntax in this case but is similar. Perhaps you tried to generalize it more. |
MAUI also supports Trim OnPlatform. in the example:
When the RuntimeIdentifier is set it removes platforms not supported by the runtime. In the previous example if the RuntimeIdentifier is set to net6.0-android the compiled xaml is:
|
@workgroupengineering @maxkatz6 This is an important point. Ignoring the syntax differences with Maui for now, Maui would not require the DataGrid nuget package on platforms it isnt used. Avalonia will require it... which doesn't make a lot of sense. This should probably be adjusted to more closely follow Maui. |
@robloo this "On" syntax is also supported in avalonia. https://github.com/AvaloniaUI/Avalonia/blob/master/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OptionsMarkupExtensionTests.cs#L296-L303 @workgroupengineering the main point of this removing is to avoid creation of unneeded branches in the code. Avalonia already does it. Also, MAUI example works with TargetFramework and not runtime identifier, and it won't work well with libraries, which target, let's say, "net6.0" to support any platform. In Avalonia with XamlX we have possibility to inject actual "switch" expression in the IL code. But it won't remove the branch completely, so package dependency would still be required, as @robloo pointed. |
Yes, I saw it was supported however the syntax is different as shown below. Maui is much more obvious in the common case of switching controls per-platform. However, Avalonia appears to be a bit more generically useful (I'm not sure how/where options are defined though). Maui <OnPlatform x:TypeArguments="View">
<On Platform="UWP, macOS">
<Label />
</On>
<On Platform="Android,iOS">
<Grid />
</On>
</OnPlatform> Avalonia <local:OptionsMarkupExtension>
<On Options='OptionA, OptionB'>
<SolidColorBrush Color='#ff506070' />
</On>
<On Options=' OptionNumber '>
<SolidColorBrush Color='#000' />
</On>
</local:OptionsMarkupExtension>
For the first version that is probably fine. Long term it's going to be a problem though. Packages/controls will diverge in some cases between Desktop and Mobile. |
In case of DataGrid it's probably unavoidable anyway. For two reasons:
So that's definitely a long-term problem, also partially blocked by the runtime. |
I don't see what's a difference between these two? Except "Platform" was renamed to "Options" to be more general. And typearguments are optional. <OnPlatform> <!-- x:TypeArguments="View" can be added, but not necessary -->
<On Options="Windows, macOS">
<Label />
</On>
<On Options="Android,iOS">
<Grid />
</On>
</OnPlatform> |
Speaking about conditional content, I can mention TemplatedControl with different StyleSelectors. ValueRenderer.axaml.cs
ValueRenderer.axaml
|
To reduce load time or to increase layout performance one may need to conditionally detach layout controls from visual tree. For example, when layout part loads images from the Net, but a user has disabled image loading in the application settings, XAML layout does not need to load the view part responsible for image showing.
In Angular, there is a NgIf directive that solves this issue. So please, take a look: https://angular.io/api/common/NgIf
So, maybe Avalonia framework should have such control in its standard library? Something named AvalonIf that we can use in our application like this:
Thanks!
The text was updated successfully, but these errors were encountered: