All right, guys.
So while I was away, I kind of refactored quite a few files in this project.
I'm going to walk you through each line, and we're going to test it together.
I did that because I didn't want you to sit and watch me type, but I will be walking through each line.
You can hit pause and replicate as I go along with the explanation where you need to write.
So number one, let's go over to the main page and let's comment on it all of what we did initially.
All right.
I'm going to restate it a bit, because now I have a new grid and this grid is going to have a column
spacing of one row, spacing of one and putting on five.
Once again, let your creativity be your guide.
I'm not here to dictate what it should look like.
If you have different ideas, then no problem.
Then we're going to have.
So role definitions and some column definitions.
So initially we would have inside of the grid tug written rule definition and then we were all totes,
you know, comma separated rules, comma separated columns.
Here's another.
We can do it.
We can start a grid, draw definitions.
And then you can define each row, whether it's sitting at the auto or star or to an actual value,
whatever it is you want to do.
You can do that.
And then for the grid, the same thing.
We're going to have just one column.
Then I'm going to have a vertical stack layout and I'm setting the putting here to five and the margin
to nine.
I'm also sitting in the first grid row, so that should fall into this grid, Earl.
Now, this vertical stack layout will have three entry controls.
Right.
So enter here represents basically a text box.
It's just like an input with type equal text in Ishmael.
We just set entry.
I gave it a name.
Granted, this name would be more useful if we weren't using the NVM pattern, where name of course
would allow us to access it from the code behind and access the value and interrogated.
But I still put a name there because it's just like second nature to me to always know what my input
controls the names are.
Right.
I put a placeholder so each one has a placeholder.
Enter the appropriate value accordingly.
And then we have the text and then we're binding to some properties that I have added.
So if you go to those properties, those are in our car list view model.
And never mind anything that I haven't gone through as yet, just focus on the differences.
So here we have the three new fields, which of course are no observable properties.
And these observable properties are what we're binding to in our XAML file, right?
In our main page.
So main page.
No, you get this over here.
Main page has these three entries and the text for the entries binding to the respective property from
our view model, nice and simple, right?
We've already gone through a binding so we can appreciate that we can bind to print, but we can also
bind for input.
They call this one two way binding, right?
Where if a value is present, it will be displayed.
And if a value is there when I want it, I will get it.
Then we move on to the button.
So we already have the button to get this button.
I'm putting two buttons and I'm putting one above the other, so I'm just putting this one in the second
grid.
So this new button, the text is our car.
So after we fill out these three fields or however many fields you had, then you can add the data.
It's in the second grid.
I'm still binding it to the is not loading and the command here would be add car.
That's a command that we we're going to go through together and then we have a margin.
Once again, creativity can guide you there.
Then we have the original button which said fetch cars and this binding says get car list command and
we know that one.
So you actually could just cut and paste or just go to the originally, come into the record, copied
and pasted to and just make sure it's in the appropriate grid role.
Then I moved the refresh view down to grade four and I didn't change much except I guess down here in
the grid I modified it to have two columns.
Star and auto and four hour frame.
I put that in the first grid column.
And then I created a horizontal stock layout, which I put in a grid column, one in which I put a button,
right?
So this button is going to be a delete button.
So we will be creating and then we'll see the list as we create.
And then we can remove bonus challenge.
I am going to do it, so I'll take that in with the final section for the section.
But I challenge you to put in an update button so you will see how we do the add, how we do the delete.
I'm challenging you to come up with an update operation, right?
So we have our button to delete.
The command here is going to look very similar to what we did with the tap gesture.
Actually, it's the same code except the command is going to be delete car command as opposed to get
card details.
Right.
So this is going to be called delete car command.
And another thing that is going to change is the binding parameters.
So initially we have said full stop to me and get me the entire object.
Now that we're dealing with a database, I don't want to pass objects around.
So instead I'll just pass the idea.
And then when we get to where we need to get to, then we can see, then we can keyword the database
and get the real object and then move along, right?
So now I'm changing this to ID instead of the full stop.
And like I said, this is pretty much the same and the path is just going to be slightly different.
And that's really it for main page.
It's not tool, but right?
It's just a new grid with some new rules, the new entry points, a new button, and some changes to
our grid here and over the grid with the columns and the new button in the new horizontal start layouts.
So if you want, you can actually just create the new button here and we can call this update even though
the update button usually comes before delete.
So update versus delete and leave the binding parameters and leave the path here empty.
Right.
So you can fill that out when you're ready.
So let's just jump over to our view model and see or changes.
So the first thing I did was in the car list view model, which kind of and this change actually kind
of almost invalidates the need for our button to fetch the cars.
But this function call as soon as the list of the car list view model is loaded, you would actually
just go ahead and load the cars.
Right.
So, of course, you know that once the cars are loaded, they're loaded into an observable collection.
And then all of that, Bob, is up to the user interface.
So it's that the list would automatically load without any button click event.
Right.
So that's one thing.
This is optional though.
You can choose to or not.
So that's up to, you know.
Let us look at some of the card details.
I'm not ready for the cards, is this.
Look at the ad car and the delete car.
All right.
So ad car, brand new command.
I'm just doing some simple validation here, making sure that none of these is empty.
If any of them is empty, then I'm going to display a show message saying invalidate these, insert
valid data, and then we return.
All right, otherwise, let's go ahead and build that car.
And then I'm just filling on make model and then based on our observable properties coming over from
our form, right?
So make model Vin, those are the same things I'm checking here after we've formulated this object of
car that I'm just going to call my car service and add car.
So let's see what that method does.
So if I jump to that method of it, add car, it takes an object of car.
We call in it just to make sure that we're connected to the database.
I check if the car object is null.
If it is that I throw an exception.
Of course you can decide how you want to handle that.
And then we say result is equal to then conduct insert.
So it's this easy.
I just say con, give me an object, insert this new object of type car and then I'm setting the status
message.
Remember I said that status message should be public.
So status message is equal to either this message.
If the result comes back as zero, that means it failed or insert successful.
If we get an exception, then we return that status message accordingly.
Right?
So the purpose of that status message and always for the alerts that we display afterwards.
So I'm just going to say alert and this is misleading.
So let me just call that info.
So it's more generic, right?
Because it could be insert field or insert was successful.
So I don't want to say successive it failed.
And then after that I call get car list.
So the reason for this call is to show how dynamic that list can be.
As soon as I add the car and it's successful and I click okay, then the list would reload and show
me the latest car.
Right?
So I'm just showing how you can accomplish that kind of real time feel in your up.
Then we move on to delete car so far.
Delete car.
I'm taking up our image of I.D. and then I'm checking once again.
Is the idea valid?
If it is not, then I display.
I shall alert.
Otherwise, I'm going to go ahead and try to delete the car.
So let's see what delete car does.
Delete car.
Essentially does that same track catch.
And it does end in it.
And then we return the result of con table car.
So we saw something like this when we're getting all cars instead of tourists, however, I'm going
to say delete and then a lambda expression where we look for the red card with the matching I.D. that
is coming in.
Right.
Once we have that, then, well, I could actually return a status message and see the Nissan successful
here I'm seeing fail to delete data if we catch an exception and ultimately I can return zero.
No where it's coming from.
I actually did.
If return if result is equivalent to zero, then we display invalid data.
Please insert for the data because that means the database operation failed.
Right.
Well, I think this is actually just my poor job of copying and pasting, so I should probably say something
like Operation Field.
All right.
So you see, you can either set the status message and return the status message and use that here or
you can of if else statements either way if it was successful.
I would just say failed.
If it was successful.
Then and usually results would return one when it's successful.
So if it was successful at what it was doing, then we display an alert that it was successful record
successfully removed, and then we reload the list again so that that newly deleted record no longer
shows up.
All right.
So let us back now and look at our card details.
So in card details, I modified it to take an integer I.D. parameter.
Right.
So remember that we are that the whole object is what we're passing initially.
Now I'm just taking the I.D., the ID, easier return.
So there are some inconsistencies.
Of course, we could bolster this and Mr..
Put in enough alerts and error handling and so on.
I'm just giving you the general ideas.
You can fill them in as you need to.
And then the next thing that I want to do if we don't return, is to go to the card details page.
We know that part already.
This time I'm going to just build out a whole navigation string and actually tackle the navigation properties.
Right.
So there are two ways you could actually do this.
We could have that directory key value here and I could pass in the string name of the parameter which
would be ID as well as the value which could have been an object like we did before or in this case
an integer, because the type of the parameter is object.
So it's not being strict as to what data type it's willing to accept.
So I could pass in that integer as well.
I could retain that syntax, but we already have an example of that syntax.
So here's another example where I'm just interpolating the name of the page with a question mark to
signify query parameters or query string values.
The name of our first course string parameter and the value it gets.
Which is it?
So that means we're going to now navigate to our details speech.
So let's go over to the Details View model.
Let's see us in the details.
And what I can say, I was testing in the details.
You model modifying the query property here to just say name of any name of it.
I believe last time we had car and car, one of them said Name of car.
The other one was car and street.
So I'm just showing you whether you want to use strings or you want to use name of.
As long as you get the string name of what you intend to get, then you're all good.
So this one binds to the observable property of ID.
And then this one is just a navigation parameter, right?
So when our data gets here, the thing is that it's not going to automatically bind here yet because
of how the piece lifecycle works.
In fact, let me just simple.
Was it a car detail speech?
What really happens is that even when it hits the constructor, those values, whether it was car or
the ID, that's still not set even after it goes through all of this.
It's not sets until it gets the are navigated.
So once it hits this event, if you were to look back at what values were in the binding context, then
you would see that the idea.
And the car would have then been set, or the idea at least would have been set.
Obviously the car isn't being set now because we're not passing over the car property, which is why
I've enlisted the services of this, this new interface called I query attributable and I query attributable
know once you inherit from this and notice are doing what multi inheritance.
So we already inherit from base view model and then we can inherit from as many interfaces after that
as we may need to.
Right.
So I query attributable interface allows me to implement this method which says apply query attributes
and it takes in that same dictionary of string and object.
All right.
So what this is going to do now is strip any incoming query properties that well, obviously they're
incoming under not set our really access them until a certain point where it probably is too late.
So this allows us to scrape those values out and I can now set my local IDs value.
So the.
Integer equivalent.
Because what really happens is that this is going to send it to us kind of like a strip.
What this is to strip.
But because it's object, it doesn't really know.
Right?
Because remember, it's string.
An object string is a name.
An object is the value.
So it doesn't know if this is an integer or a string or whatever, it doesn't care.
So we have to do our unnecessary conversions.
So just to make sure nothing malicious is coming in, we're going to decode it and then we strip it
all.
So I can say query and I could say IED, sorry, name of IED.
Or I could have easily just said IED, right?
We do that.
So it looks a little bit more natural and less confusing.
So query, get me the parameter with the key IED.
And then convert it to string.
But then I'm also just going to convert all of that to.
In 32.
All right.
Actually, that's a string.
Might even be.
Optional.
No, it's not optional because the code needs a string, right.
It does need a string if that's not really the focal point.
The point is that I'm getting the idea and then know that I have the idea I can set my observable car
to be the value of abort car service.
Get car what is get car doing get car.
Is doing the same track it does in it.
Then it goes to the table and then instead of doing the list or a delete, this time it does a first
or default with the same kind of lambda expression.
So it give me the first record that has that idea first or default is either going to return the data
or return the value null if it goes that far without anything that we're going to return anyway.
Right.
So that point, that's another challenge.
You could actually figure out what you would want to display to the user if no record was found.
Right.
So those are little things that you can consider.
I haven't made any changes to the actual card details page.
You know, you can fill that out if you would like to.
But at this point, I'm more interested in taking this for a spin.
So once again, you can always hit pause.
I hope I win slowly enough, but you can always hit pause and focus on the parts that you may have found
a bit challenging.
And then you can fill in the blanks accordingly.
And I'm getting an error here because I left this blank.
Let me just say update car command.
And while I'm at it, I'm just going to go ahead and create that new command.
So I command.
And in a sing.
Async task.
And I would just say update car.
I would say the entirety.
So you see, there are a number of ways we can do things right.
We could always just pass in the I.D., query the database, or we could just pass an entire object.
And I'm just leaving that nugget with you so you can make a decision as to how you implement this.
And a good idea for implementing this would be that when you click update, you would actually fill
the same form up top.
With the data, right?
Because you already have the form and update on it and it and that should be it.
It's not it doesn't really matter.
But an edit form would actually have the same feels as a create at least in this situation.
So it would be good if you just update the values that are here with what you're able to update, probably
change the text of the button so that you know when you're ready to click Submit or rather when you're
editing this no longer says add car, it says update car, you know, stuff like that.
So get get creative, right?
So like I said, I was more interested in testing and running it through so we can make sure that everything
works.
So Invision of course keeping up a little while, your code, it can be resource intensive on your machine,
but it does make the experience much better.
All right.
So you can see here, I entered some very silly car.
If I tap it, we navigate over to our editor speed.
So the E and R, if I click delete, I will see recorder move successfully, click okay.
And then there's nothing there.
So that's that real time field, right?
Let's try adding a car.
So test.
Water test.
I know.
Just to test again.
And then we can click add car insert, successful click.
Okay.
And then it appears right once again, kind of realtime if I click fetch cars.
Okay, well, no, I really don't need that fixed car's button and well, we could still do the refresh
if we wanted to.
Aren't it's once again optimal design wise.
We could also put in a button that is clear form.
Right, because see I just added car and all of the all the values are there so we could clear the form
after we add or and or add another button that is clear form.
I'm just giving you ideas, right.
Because practice makes permanent.
So you want to play around with this thing and get more comfortable with it.
When I navigate the test, there we go.
We are seeing the details and I can always go back.
Right?
So that's pretty much it.
So we have done.
CRB I left the you all right.
So in order creates we know what to read and we know how to delete.
You can work on the update and just have fun with that.