How to data bind an embedded object with C# Markup

I have an Embedded Model:

 public  class Address: EmbeddedObject
{
    public string Locality { get; set; }
    public string Pin { get; set; }
    public string PostOffice { get; set; }
    public string District { get; set; }
    public string City { get; set; }
    public string State { get; set; }
}

Another RealmObject Model Which have Address Model as a Property:

public class MilkMan : RealmObject
{
[PrimaryKey]
[MapTo(“_partition”)]
public ObjectId MilkManId { get; set; } = ObjectId.GenerateNewId();
public string PreferredLanguage { get; set; } = “English”;
public string Name { get; set; }
public DateTimeOffset DateOfBirth { get; set; }
public string Sex { get; set; } = “Male”;
public Address Address { get; set; }
public IList Incomes { get; set; }
}

Than I initialize the MilkMan Model like this :

MilkManProfile = realm.All().FirstOrDefault();
if (MilkManProfile == null)
{
MilkManProfile = realm.Write(() =>
{
var address = new Address();
var profile = new MilkMan (){ Address=address};
// set properties if necessary
return realm.Add(profile);
});
}

The issue is that Address property of the MilkManProfile remain null even after initializing it.

That should not be the case. Are you sure you’re entering the Write block there? If you can create a simple project that reproduces this behavior, I would love to take a look.

The Link to the sample project. I noticed that when I bind the Values with XAML it works. But the UI in my app is build with C# markup and causing this issue.

I ran the project that you attached and Address is correctly initialized as a non-null value. Are you sure you are entering the Write block at all? Perhaps you had a MilkManProfile object already inserted in the database and you just never trigger the write block?

I believe I don’t need to enter the write block . I am binding the Realm Model directly with UI. The MilkManProfile object properties are persisted without write block., except Address Than Address should also save itself without write block as it is a part of MilkManProfile. I am binding the UI like this:

 new Entry{}.Bind(Entry.TextProperty,$"{nameof(vm.MilkManProfile.Address)}.{nameof(vm.MilkManProfile.Address.Locality)}")

As I didn’t define any property in the ViewModel. I don’t have any thing to assign in the write block.

You can’t create an object from the UI like that. Your binding binds the entry text to vm.MilkManProfile.Address.Locality. If Address is equal to null, the databinding engine will not attempt to create an object to then set the Locality.

1 Like

In my sample project I already initialize the Address on MainViewModel:

if (MilkManProfile == null)
        {
            MilkManProfile = realm.Write(() =>
            {
                var address = new Address { };
                var profile = new Profile() { Address = address };
                // set properties if necessary
                return realm.Add(profile);
            });
        }

In the above code block the Address object is already created. Now on SeondViewModel it should update the properties from the UI.

This was my point when I asked you whether your code enters the Write block. If MilkManProfile is not null - e.g. because you previously created the database and already created the object, you won’t enter the write block that assigns the address to a non-null value.

Please show me how to accomplish the persistence of Address. I don’t want a write block but want to update the database directly from the UI.

Not sure I understand what you mean. You already have a Write block in the code snippet that you posted:

if (MilkManProfile == null)
{
    MilkManProfile = realm.Write(() =>
    {
        var address = new Address { };
        var profile = new Profile() { Address = address };
        // set properties if necessary
        return realm.Add(profile);
    });
}

My question is - if you put a breakpoint before the if-clause, can you inspect MilkManProfile and check if it’s null. If it isn’t null, can you check whether Address is null? As already mentioned, my expectation is that MilkManProfile is not null - i.e. it was created previously, but Address is null because you created the profile before you added the Address property. If that’s the case, then the UI cannot set the Address property to anything because you don’t have a databinding that does this. Your databinding sets Address.Locality, which will only happen if Address is not null.

What you can probably do is add another check in your first view model along the lines of:

if (MilkManProfile.Address == null)
{
    realm.Write(() =>
    {
        MilkManProfile.Address = new Address();
    });
}

I added the check on my first ViewModel.

if (MilkManProfile.Address == null)
{
realm.Write(() =>
{
MilkManProfile.Address = new Address() { Locality=“”,Pin=“”};
});
}

Than this line

var place = MilkManProfile.Address;

When I hover the cursor over Address in the above line I get this expression:
image

I don’t know why Address remain null even after initializing it.But after continuing on from the above line when I hover over the place variable I get this expression:
image

Is it possible for you to make the necessary changes in the sample project. Then post the correct code over here.

As I already said, the sample project works fine for me and I don’t see address being null there

Please go through the below steps:
On MainPage → Click navigation button and navigate to SeondPage → Fill in the Locality and Pin values-> Press BackButton and come back to MainPage. Now when I again go back to SecondPage The locality and pin values are not persisted. Whereas they should persist because the Address is already initialized and both the values are data bound with the Realm Model.

This is a different issue than the one discussed, and I believe one that we’ve already helped you solve. The Address property is not null when I navigate to the second page - it’s initialized, but the fields are null. When you make changes via the UI, those don’t get reflected in the database because your binding is wrong - you’re trying to bind the text field to Address.Locality but there’s no such property on your view model. The correct binding string is MilkManProfile.Address.Locality. To achieve that, you need to add {nameof(vm.MilkManProfile)}. to both .Bind calls.

I was binding it incorrectly. I am grateful to you for your patience and support. The correct binding syntax is

Bind(Entry.TextProperty,$"{nameof(vm.MilkManProfile)}.{nameof(vm.MilkManProfile.Address)}.{nameof(vm.MilkManProfile.Address.Locality)}")

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.