3
votes

I have a grid element with the x:Load attribute bound to a variable in the page:

Page.xaml

<Page>
...
    <Grid x:Name="grd" x:Load="{x:Bind LoadGrid, Mode=OneWay}">

Page.xaml.cs

public sealed partial class Page : Page
...
bool LoadGrid;

After receiving the passed argument from the OnNavigatedTo event handler, I set the value of LoadGrid accordingly:

request = (Request) e.Parameter;

if (request == null)
    LoadGrid = false;
else {
    LoadGrid = true;
    InitializeComponent(); // Tried adding this to refresh the controls.
    grd.Loaded += grd_Loaded;
}

When the line grd.Loaded += grd_Loaded; is executed, an ArgumentException is thrown:

An exception of type 'System.ArgumentException' occurred ...
Delegate to an instance method cannot have null 'this'.

I check and the value of grd is null even though the x:Load property is true and the binding mode is OneWay (the control "checks" for updates in the bound value).

Edits

ATTEMPT 1

Calling this.InitializeComponent() to re-init the controls.

ATTEMPT 2 suggested by @touseefbsb:

Use the MVVM approach to create an event for updating the property value.

ATTEMPT 3

Tried .FindName("grd") after setting the load value, didn't work.

2
Is the Grid the root element in the page? If so, you can't use x:Load there. It has to be one level deeper. - James Croft
No, it is inside another grid. - Phantom
Doesn't x:Bind only trigger once ever? I'm usually in WPF, which doesn't have this binding, but I think I remember reading about it at some point. - Bradley Uffner
@BradleyUffner This is correct, {x:Bind} defaults to OneTime, while {Binding} which is used with WPF defaults to OneWay. docs.microsoft.com/en-us/windows/uwp/xaml-platform/… - fourwhey

2 Answers

2
votes

Unlike in prior XAML platforms, the OnNavigated method is called before the visual tree is loaded.

So, you could register the Grid's loaded event in the Page's loaded event handler like the following:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    var request = e.Parameter;

    if (request == null)
        LoadGrid = false;
    else
    {
        LoadGrid = true;
        InitializeComponent();
        this.Loaded += BlankPage1_Loaded;
    }
 }

private void BlankPage1_Loaded(object sender, RoutedEventArgs e)
{
    grd.Loaded += Grd_Loaded;
}

private void Grd_Loaded(object sender, RoutedEventArgs e)
{
    Debug.WriteLine("Grd loaded.");
}
0
votes

the OneWay binding also required the property to use INotifyPropertyChanged interface.

First of all your LoadGrid should be a property and not just a field like following

public bool LoadGrid {get; set;}

after that you need to implement the INotifyPropertyChanged which is best to be used with a ViewModel ( MVVM pattren )

make a ViewModel class with the implementation.

public class PageViewModel : INotifyPropertyChanged
{
    private bool loadGrid;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };


    public bool LoadGrid
    {
        get { return this.loadGrid; }
        set
        {
            this.loadGrid = value;
            this.OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

after that make a property which is of type PageViewModel within your page like :

public PageViewModel vm {get; set;} = new PageViewModel();

then within your OnNavigatedTo() method you can set the property like you want. and you dont need to call InitializeComponent again to refresh anything.

if (request == null)
    vm.LoadGrid = false;
else {
    vm.LoadGrid = true;
    grd.Loaded += grd_Loaded;
}

the last change you need to make is a little change in xaml just bind to vm.LoadGrid instead of LoadGrid like following :

<Grid x:Name="grd" x:Load="{x:Bind vm.LoadGrid, Mode=OneWay}">

more details on data binding in depth : https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth