-
-
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
x:Load attribute #6853
Comments
A basic implementation would be quite easy to do. We could have something like this: public class DeferLoad : Control
{
private IControl _control;
public static readonly StyledProperty<bool> LoadProperty = AvaloniaProperty.Register<DeferLoad, bool>(
"Load");
public bool Load
{
get => GetValue(LoadProperty);
set => SetValue(LoadProperty, value);
}
[Content, TemplateContent]
public object DeferredContent { get; set; }
public IControl Control => _control;
static DeferLoad()
{
LoadProperty.Changed.AddClassHandler<DeferLoad>((c, e) =>
{
if (e.NewValue is bool v)
c.DoLoad(v);
});
}
protected override Size MeasureOverride(Size availableSize)
=> LayoutHelper.MeasureChild(_control, availableSize, default);
protected override Size ArrangeOverride(Size finalSize)
=> LayoutHelper.ArrangeChild(_control, finalSize, default);
private void DoLoad(bool load)
{
if((_control != null) == load)
return;
if (load)
{
_control = TemplateContent.Load(DeferredContent).Control;
((ISetLogicalParent)_control).SetParent(this);
VisualChildren.Add(_control);
LogicalChildren.Add(_control);
}
else
{
((ISetLogicalParent)_control).SetParent(null);
LogicalChildren.Clear();
VisualChildren.Remove(_control);
_control = null;
}
InvalidateMeasure();
}
} Usage: <CheckBox x:Name="Load">Load</CheckBox>
<example:DeferLoad Load="{Binding #Load.IsChecked}">
<Button>Hello I'm deferred content</Button>
</example:DeferLoad> (you can just copy that class to your app right now, BTW) Then XAML compiler could rewrite: <Button x:Load="{Binding LoadButton}" >Test</Button> into <DeferredContentContainer>
<Button x:Load="{Binding LoadButton}" >Test</Button>
</DeferredContentContainer> which is also kinda easy to do. But we need to actually design the feature first. How does it work with x:Name and fields in codebehind? |
FYI: This is heavily used on the Uno Platform for mobile devices (and even desktop due to how slow it is). There was just no way to get acceptable performance otherwise. I really think it's going to be needed for Avalonia as well once mobile support comes online and is more widely used: #1602 (comment) I still think #1434 titled 'Conditional XAML' is confusing as that is a different feature of Microsoft XAML. I would vote to keep this issue open tracking x:Load specifically. |
For Edit: I realize I probably misunderstood your question. I imagine there is a placeholder used by WinUI after skimming through the docs. Setting the Name property would have to be deferred too somehow; although generated code references for named controls in the window/page would be the same. The Uno Platform implementation has answered these questions though so it might be useful digging through how they did things. |
I was thinking about rewriting x:Load to DeferredContentContainer approach and it seems that it breaks several interactions with the rest of the framework:
So while being a feasible API to provide as is, we can't use it as direct x:Load implementation. However, from my understanding x:Load requires special support from container to properly hide the placeholder from the user code, i. e. it doesn't seem to be possible to assign <local:CustomControl x:Name="Parent">
<local:CustomControl.Control>
<local:MyButton
x:Name="HelloWorld"
x:Load="True"
Content="ASDASDASD" />
</local:CustomControl.Control>
</local:CustomControl> fails with
(tested by @maxkatz6 ) I don't think we need that special support for property assignments since we could just set them in deferred way like we do with bindings. For panels however that special support seems to be provided by UIElementCollection. The problem is, we don't have separate Items and ItemsSource like WPF/UWP do, so we can do that on collection level. The way I see it could be done is by creating an special shadow collection that's linked to the actual list and populated by compiler instead of said list. Shadow collection would track the load status of individual elements and push changes to the target list. The only limitation of that approach I see is that target list has to be essentially owned by XAML and not modified by anything else, which, I suppose, is OK for most cases. For cases where it's not appropriate, one could use |
Maybe we need to move to having a separate |
@kekekeks : Hello, This class works well if the condition change but not when the DeferLoad is created (as the DefferedContent is not assigned yet. Is there any workaround for this ? |
You can change the |
Perfect, thank you ! |
Is your feature request related to a problem? Please describe.
https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/x-load-attribute
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
The text was updated successfully, but these errors were encountered: