Wire Up the WPF Shopping Cart - A TimCo Retail Manager Video

แชร์
ฝัง
  • เผยแพร่เมื่อ 17 ม.ค. 2025

ความคิดเห็น • 142

  • @onyebuchiboss
    @onyebuchiboss 5 ปีที่แล้ว +2

    That last bit of speech was Inspirational Tim. Imma keep pushing, sometimes i feel i will never get to the level i wanna be in coding, but i will try.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      You are welcome. Just keep pushing.

  • @tinumurymury38
    @tinumurymury38 5 ปีที่แล้ว +4

    Hi Tim,
    About the hack in the AddToCart() method.
    I replaced Cart.Remove and Cart.Add with a simple Cart.ResetBindings();
    As far as I can see, it's working fine. The quantity is updated and the item stays in place.
    Have a great day!

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +1

      Good suggestion. I'll add it to the list to try.

    • @objectaware5296
      @objectaware5296 5 ปีที่แล้ว

      Excellent!

  • @harag9
    @harag9 5 ปีที่แล้ว +1

    Thanks for the video, WPF is quite different from WinForms which is what I work on. As for walking away from a problem, 100% agree - it usually keeps me awake at night and suddenly the solution pops in before I drop off to sleep... then I forgot in the morning :) Keep up the excellent work Tim, Many thanks!

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      A shower can help too. That's where I come up with some solutions. I came up with a number of example projects while on the elliptical at the gym recently (those are always hard to design - varied so they aren't boring but simple so they aren't distracting or confusing).

  • @ben.thornhill
    @ben.thornhill 4 ปีที่แล้ว +1

    Great content as always!

  • @truongnam5395
    @truongnam5395 2 ปีที่แล้ว

    all of this videos help me alot sir!! thank you!!!

  • @ahmadkelany
    @ahmadkelany 5 ปีที่แล้ว +1

    Hello Tim,
    Great tutorial as always,
    My suggestions:
    1. Adding retail price to the products and cart lists.
    2. Modifying the data template instead of adding a new property as we probably will need to display more info (e.g. item retail price, item image)






    3. Using LINQ instead of looping might be better
    return Cart.Sum(ci => ci.Product.RetailPrice * ci.QuantityInCart).ToString("C");

    • @ahmadkelany
      @ahmadkelany 5 ปีที่แล้ว

      4. Implementing INotifyPropertyChanged interface on the cartItemModel solves the updating quantity propblem:
      public class CartItemModel : INotifyPropertyChanged
      {
      public ProductModel Product { get; set; }
      private int _quantityInCart;
      public int QuantityInCart
      {
      get => _quantityInCart;
      set
      {
      _quantityInCart = value;
      RaisePropertyChanged();
      }
      }
      private void RaisePropertyChanged([CallerMemberName] string propertyName = null)
      {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
      public event PropertyChangedEventHandler PropertyChanged;
      }

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      Thanks for the suggestions. I'm adding them to the list.

  • @Empathies92
    @Empathies92 4 ปีที่แล้ว

    I really like the motivational speech at the end of the video.
    I did the Tournament Tracker course before this one, and I loved the fact that we did everything manually, which made me understand every single piece of code.
    In this project some things seems to happen Automagically (got that term from another teacher) which makes it harder to follow the logic sometimes.
    Either way I'm glad I'm still keeping with the course, and I'm thinking of commenting every bit of code after the course to help me understand every single bit of it :D

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว

      Yeah, this is for intermediate to advanced users for practice, where Tournament Tracker was for beginner to intermediate developers. As the applications progress in complexity, there is more that is assumed you will know. It takes some work to get up to speed for a more advanced application, but by sticking with it like you are, you will really grow as a developer. Great job!

  • @TheCheriaTebessa
    @TheCheriaTebessa 5 ปีที่แล้ว +1

    Thanks for tutorials

  • @anthonyclanagan9914
    @anthonyclanagan9914 2 ปีที่แล้ว

    Very good lesson, thanks for making it.

  • @jourvh
    @jourvh 5 ปีที่แล้ว

    I love this course!

  • @jeffmaness7242
    @jeffmaness7242 5 ปีที่แล้ว +2

    Hi Tim. Great series here! Your videos have helped me learn to SQL and to code in C#. I now have a developer job and I see a lot of parallels with some of the topics you cover in the series. I did have a question:
    When you add the hack of removing and adding back in the cart item, I peeked ahead and saw you had a video about using automapper to fix this. I was able to get the list working nicely by simply calling Cart.ResetBindings() in the AddToCart method after NotifyOfPropertyChange(() => SubTotal). Do you see any drawbacks to doing it this way?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      Yeah, that is a hack as well. ResetBindings will reset everything. So, if you had your cursor on the third item in the list, after the reset it will be at the top. The fix (using INPC) is in line with how notification of changes normally happen.

  • @RavianXReaver
    @RavianXReaver 5 ปีที่แล้ว

    Thanks Tim!

  • @steveteece8889
    @steveteece8889 5 ปีที่แล้ว +1

    Hi Tim,
    Instead of keeping the quantity in stock inside the ProductModel, would it be better to add an Inventory table to the database and keep the quantity in stock in that table? Each ProductId would have a corresponding item in the inventory table...
    I'm really enjoying this series, and am learning heaps as usual.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +2

      Good question. We have an inventory table where we list the products we purchase for the business. However, the aggregate amount is stored in the product table. We can always refresh that number if we think it is off by adding up the purchased inventory and subtracting out the customer purchases.

  • @objectaware5296
    @objectaware5296 5 ปีที่แล้ว +2

    A couple of suggestions and observations:.
    It seems to me there is a HUGE assumption that there will only be a single cash register. In real life, most stores have several cashier stations. Keeping the updated product records in the UI code makes it impossible to implement multiple stations. IMHO, we might as well do away with the API as it is not being used in a SOA application but rather as a means for adding different UIs.
    @33:33 There is no need to compare the entire product object when each ProductModel is unique by ID from the DB. The ProductModel should be updated on the db if we are going build a real world SOA application. The product should be pulled from the db to insure there is sufficient stock for the order as the item is added to the cart and the product record QuantityInStock updated in the db
    @41:42 Adding a comment like ////HACK does nothing for being able to come back to that piece of code after a few weeks or months. I prefer to use the //TODO: statement so I can view the TaskList (ctrl+w t) in VS to see if there are things that I need to address at any break in development . I also add a task to the Kanban board and note the task id in the //TODO for things like hacks. We used // TODO in the Tax, Total, and Subtotal we should consistently use a best practice pattern. BTW, you can add custom tokens like HACK in the Tools | Options | Environment | Task List - the problem with using them is that other devs that come after you may not have the custom token defined.
    As always, enjoyed the video and starting to get the hang of WPF w/ CaliburnMicro

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +3

      I posted a reply to this yesterday but it seems to have been eaten by the system. I'll try to recap.
      There is no assumption of only one cash register. There can be multiple. I think the confusion here is on the manual update in the UI of the quantities. We do that just for the current user. When they add something to the cart, they haven't purchased anything yet. However, we want to make it responsive for them. Otherwise, they could exploit the system (or really just make things messy) by adding more items to the cart than the total available. It is only when they purchase the items in the cart that we will go back to the API, verify the quantities right then, and make the purchase. In the off chance that someone else has purchased the item, we will have to put in an "I'm sorry, this is now out of stock" process. Amazon actually does this after the sale. I want to do it before the sale is finalized (after they hit "buy"). We could continually update the quantities in real-time, either with polling (not quite real-time) or with something like SignalR. That might be something we pursue but we do have to balance that with the load on the database. It may come down to a broadcast when something is purchased that alerts us to the new remaining quantity. That would probably be the most efficient.
      I'm aware we have the ID of each product in the object but in this case, comparing the objects themselves is more efficient. Remember that the variables don't hold the object, just the location to find the object (the address). So, when we compare the two variables, we are actually just checking to see if they both have the same object location (the address of the "house"). That is more efficient than each object going to the object, pulling out a value, and then comparing those two values. Most of the time, an object comparison is not the right choice but in this case, it is the correct choice.
      I'm not sure why you don't have HACK in your Task List. I've had it in every copy of Visual Studio I have owned for years. It isn't something I added, either. That is one of the options that comes from Microsoft. Another is UNDONE. These are standard flags beyond TODO, although they aren't as used. TODO indicates that something is not complete. The code is complete but I don't like it so I mark it as a HACK so that when I come back to clean up the application, I address that spot.
      Thanks for jumping in and discussing these.

    • @objectaware5296
      @objectaware5296 5 ปีที่แล้ว

      @@IAmTimCorey With the WPF interface you must believe that the checkout process involves physical items brought to the cashier’s station for check out. The quantity in stock can be reduced as each item quantity is checked out. There is no need to wait - an async process could be used without slowing the process at the register. This business logic should be held in the UI Library for the type of UI being worked. I'm not concerned about the database as there are ways to bring it to scale. The UI is unrealistic as the number of products would normally be in the hundreds and entering the SKU or scanning the UPC would be the norm, followed by product lookup from the cache. Which would be managed from the repository.
      On the CartProductModel.Product and SelectedProduct comparison, I understand why it works, comparison of the ref address. It just makes me uneasy that I’m not making sure it is the same product. Id / SKU. Comparing the Id or SKU just gives a warm and fuzzy. I can envision, the code being broken - see above with hundreds of products.
      On the Task List, you’re right HACK does come with VS. I guess I removed it and forgot. But my point remains - don’t define additional tokens beyond the supplied ones.

    • @davidmagerman4553
      @davidmagerman4553 4 ปีที่แล้ว +1

      ​@@objectaware5296 I think @IAmTimCorey is correct to go with the optimistic "Trust but verify" pattern (note comparison with Amazon). This is pragmatic, and covers most scenarios. I think we all like the idea of real-time in principal, but it adds complexity (and therefore cost).
      One thing worth noting, there are occasions where an inventory system is not completely up to date, and the on-hand quantity of an item is reported to be Zero or (worse) a negative value. This will generally be the result of stocking shelves before performing the actual "Receiving" task. In a physical point-of-sale environment there'd be no reason for a clerk to turn a customer away (due to an inventory management oversight). Especially if the the consumer physically brought the (clearly present) unit of inventory to the sales counter and pulled out their wallet.
      In contrast, a distribution center or online bidding site would need to be much more precise.
      In summary, the solution should be sized to the problem.
      Great Series! Awesome comment section! Kudos to all!

    • @objectaware5296
      @objectaware5296 4 ปีที่แล้ว

      @@davidmagerman4553 Thanks for the input.

  • @Vitalick15
    @Vitalick15 3 ปีที่แล้ว

    Thanks a lot, sir.

  • @mihaimyh
    @mihaimyh 5 ปีที่แล้ว +1

    I think you should implement INotifyPropertyChanged on the items in your BindingList (ProductModel, CartModel), so as when an item's property is changed (Quantity) it will raise PropertyChanged event and the list will raise ListChangedEvent.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      That sounds reasonable. I'll give that a shot.

    • @piotrc966
      @piotrc966 5 ปีที่แล้ว

      yep, I've done like this. I show 'QuantityInStock' too, to now how many items left.

  • @36kph
    @36kph 5 ปีที่แล้ว +1

    Are you going to make a video about .NET 5?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +4

      Eventually. It is premature to do it now, since it is just theory at this point (not saying it won't happen, but there isn't anything you can do with it right now). However, I will be doing videos on how to prepare for the future and how to convert to .NET Core in the near future.

  • @-martintheengineer-7465
    @-martintheengineer-7465 5 ปีที่แล้ว

    Best in teaching as always. After you have decremented the amount in your cart, do you don't have to update your database?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      No, because we haven't committed the change (made the purchase). The display only updates for the current user. Once they make the purchase, we will send that down through the API so that the database can be updated and the values can be updated everywhere.

  • @abc00gh
    @abc00gh 5 ปีที่แล้ว

    Thanks, Tim for the demo. How to add an event in the listbox datatamplete then when we click an item, it can update another form?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      That would really be two events - one when you click on the item that then calls another. Look at the logon event and how we trigger an event there that another form listens to.

    • @abc00gh
      @abc00gh 5 ปีที่แล้ว

      IAmTimCorey thanks again. I have figured it out using cal:message.

  • @shakil-ep2tc
    @shakil-ep2tc 4 ปีที่แล้ว

    Hi Tim, is there a reason why you opted to have a ProductItem field in CartItem instead of just extending the class? Thanks for all the content!

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว +2

      That way I can treat things as objects instead of flattening them out. I can take a selected ProductItem from a dropdown list and assign it right to a CartItem instead of just transforming part of the data (and then updating it when we add new items to the ProductItem).

  • @besnikselmanaj4940
    @besnikselmanaj4940 2 ปีที่แล้ว +3

    For me, using "Cart.ResetItem(Cart.IndexOf(existingItem));" refreshes the Cart UI correctly when adding new items.

  • @timothywestern6488
    @timothywestern6488 5 ปีที่แล้ว

    I wonder if there's an event you could look for on the Cart that would take care of that rendering issue.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      Keep watching. We fix it in an upcoming video.

  • @scottgodfrey7855
    @scottgodfrey7855 5 ปีที่แล้ว

    I always learn something new with your videos and have implemented most of your techniques in my own code (Tweaked for my program, of course). Thank you.
    I wonder if you could add a class with a generic method in the UI library that would take in the BindingList, Property, and Value (Or the updated model itself), then remove and add the item.
    Honestly, I'm surprised Caliburn hasn't added an update method to the binding list type. Xamarin is the same way. That would be so much easier.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +1

      We are going to explore some options in the next video. I think we have some good solutions to try.

  • @Joseph-gq9nd
    @Joseph-gq9nd 5 ปีที่แล้ว

    Love your tutorials :) I think you should add a progress bar when it's loading the products because we're gonna have quite a lot of products and we don't want the user just staring at the screen 'till it finishes loading and also how would I add keyboard shortcuts?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +1

      Thanks for the suggestions. I'll add them to the list.

    • @objectaware5296
      @objectaware5296 5 ปีที่แล้ว

      I would not load them to the UI but rather do a product lookup based upon the UPC / SKU of the product. The API repository should cache the most used products and return the relevant information - the order can be fulfilled from inventory and sold at a given price. Inventory should be decremented temporarily, and committed once the items are paid for and shipped.
      Why, this design? What if you have a brick and mortar store with WPF register stations and an eCommerce presence with hundreds / thousands of users . Both use the API service with well defined service calls.
      Why would you want keyboard shortcuts? The screen should be touch.
      Just my 2 cents..

  • @danilakireev6959
    @danilakireev6959 5 ปีที่แล้ว

    Hi Tim!
    Why do we need to bind the ItemSource of the "Products" ListBox to the "Products" property of the SalesViewModel and at the same time we don"t bind the ItemSource of the "Cart" ListBox to the "Cart" property of the same view model?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      I'm not seeing where I did that. I'm looking at the source code now and both the Products ListBox and the Cart ListBox are bound using the name property and not the ItemSource property. I do binding for SelectedItem and I bind for the items in the DataTemplate but I'm not seeing where you are referring to. Can you point out the time code?

    • @danilakireev6959
      @danilakireev6959 5 ปีที่แล้ว

      @@IAmTimCorey I went through the whole video one more time and in fact could not find any reference to my question. It seems that I accidentally included this binding into my code by myself. Sorry for inconvenience and thank you for your reply!

  • @jonestako4721
    @jonestako4721 5 ปีที่แล้ว +3

    thanks . can you please make UI testing tutorial?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +1

      I can add that to the suggestion list.

  • @princekmishra
    @princekmishra 5 ปีที่แล้ว

    Hi Tim, big fan of your videos. I am new to WPF and gone through each and every video of this tutorial, great content. I have also seen your video on log4net , could you please suggest (or create some video) how I can add log4net in this architecture specially if I want to log the error to the database using Web API?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      There isn't a native way of doing this but you could probably find an appender that will help you get the job done.

  • @raihanal-mamun8107
    @raihanal-mamun8107 5 ปีที่แล้ว +1

    Hi Tim,
    Instead of typing email, pass again and again, why not use ' #if DEBUG ' and input data programmatically!
    That may save few seconds!
    Thanks for your tutorials... :)

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +3

      I was tempted to do that but I also didn't want to have the issue where I forgot it and sent it to production. I really don't like those types of things in production. Besides, then I would be committing my (not so super-secret) password to GitHub. While it isn't a big deal here, I don't want to mimic bad behavior that might cause someone else to create a security breach.

    • @raihanal-mamun8107
      @raihanal-mamun8107 5 ปีที่แล้ว +2

      @@IAmTimCorey thanks for pointing it out. I really like and try to follow the way you think. not only software designing, I am also learning best practices and conventions from you. Thanks a lot.
      If someone informally ask me why I like c#, I would reply
      "it's because Tim Corey inspired me"...

  • @eofjjeifj4z38973498
    @eofjjeifj4z38973498 5 ปีที่แล้ว

    amazing

  • @mihaimyh
    @mihaimyh 5 ปีที่แล้ว

    Hi Tim,
    Watching this I remembered I was trying to find a solution when I need to select multiple items in a DataGrid.
    How can this be handled this?
    As always, great video.
    Thank you for your efforts.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      If you turn on multi-select, I believe you can do SelectedItems and map that to a List.

  • @villesipola
    @villesipola 4 ปีที่แล้ว

    Hi Tim. Great tutorial as usual. Not shure about the hack though. I would've handled it by adding a basic "ViewModelBase" class to the UI Library project that implements the INotifyPropertyChanged interface (Caliburn.Micro might even have one pre-delivered?) and from that i could derive all my models and use the NotifyPropertyChanged method in model properties. It seems like all user controls that derive from ItemsControl in Wpf use the actual models in binded collections when it comes to refreshing individual item properties in them (makes sense too). And since the library is all for WPF UI i think there is no harm for models to have these extra capabilities. Any thoughts?

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว

      The problem is that the VMs already inherit from a CM base class. You can't inherit from multiple classes so I would need to create some type of hierarchy with multiple base classes.

    • @villesipola
      @villesipola 4 ปีที่แล้ว

      @@IAmTimCorey Just finished watching "Automapper and INotifyPropertyChanged - A TimCo Retail Manager Video" where you actually did something quite close what i was thinking.
      Sorry, "ViewModelBase" was a bit misleading. What i meant, was some sort of base class for models to inherit from where from they can raise PropertyChanged (maybe via protected virtual void).
      Somewhat related to this topic: the tutorial part mentioned above in this comment got me thinking about all different "raw" versions of basically same object in the solution. I think there will be problems and confusion whenever a need for renaming a property or changing property type emerges. One of the best things in C# IMO is it's inheritance system. I think it would've had made more sense to create a "base model library" library that is shared between all of the projects. This library would then had all base models and their absolute base properties. These classes could've also been abstract or just have all basic properties marked as virtual which would then also supports direct use of the base class. These classes could also have the INPC interface without the callers in property setters. This way the INPC is there but not in use by default. And then in the UI and API libraries if you need to create a display or other classes that are somewhat different but at the same time are basically the same thing, you could just inherit from the base class and override the base properties to use the INPC caller and add other properties & methods that actually makes the inheriting class different from base. This way the property names and datatypes stay in line trough different libraries and once renaming or re-typing they will be reflected trough projects (i think this is good thing at least in initial design phase).
      Do you know if Automapper has ability to map private fields as well? If not, there's an obvious disadvantage since all property setters would have to be public. This might give some advantages to a inheritance pattern that i described since inheriting classes can be granted to manipulate these fields via the protected access modifier.
      Gonna continue watching this playlist! I've learned so much new especially from topics regarding on the API layers. Could you at some point make a video about Dapper and EF used with MySql in an Asp.Net Core API project including user authorization? I am planning on starting a project with BlazorWA and those things certainly would come in handy!
      Keep up the good work Tim!

  • @zatel3332
    @zatel3332 5 ปีที่แล้ว

    Hey, Tim!
    When I add more products in the Products table, the ListBox is expanded and then the button Check Out and other things on the right are not visible? How can I fix that?

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +1

      You can set the max height on the ListBox so that it scrolls instead of continuing to expand. You can also make your form bigger.

  • @teamracersigge6890
    @teamracersigge6890 4 ปีที่แล้ว

    Hi Tim! I have a problem, for some reason when i select a product the property QuantityInStock is equal to 0, but i get all the other values correct like Id, ProductName etc. If i check the data from the database QuantityInStock has values, What might be the problem for that? Maby a stupid question but i am new to programming😅 love the videos! Thank you so much for making them!

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว +1

      It sounds like your query to get the data has a slightly different column name for quantity than your property name. The two have to match in order for Dapper to fill the property with the value.

    • @teamracersigge6890
      @teamracersigge6890 4 ปีที่แล้ว

      @@IAmTimCorey yeah that was the problem! It is now fixed, thanks for answearing!👌👏

  • @FunTime4KidsTV
    @FunTime4KidsTV 4 ปีที่แล้ว +1

    When I click login I am getting task was canceled , when I click login again I got a response internal server error.

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว +1

      It sounds like you missed something but I don't know what. This is a great opportunity to improve your debugging skills. Track down what is happening using breakpoints.

  • @doumkatekz
    @doumkatekz 5 ปีที่แล้ว

    Tim...the font on this is small and kind of blurry even at HD 1080.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      Not sure why. I can clearly read it on my iPhone. Maybe it wasn't really 1080 at that time?

  • @aminebenhebba1891
    @aminebenhebba1891 4 ปีที่แล้ว +1

    Kinda liked the way that you finished it, its true that , we learn a lot more by searching the solution and not asking people to help the first step.
    for me the hack was
    var temp = Cart;
    Cart = null;
    Cart = temp;
    dont know if its better or worst ...

  • @NOCKSCITNEY
    @NOCKSCITNEY 2 ปีที่แล้ว

    Hi Tim
    I'm wondering if something have changed since the release of this video, some 3 years ago. I'm trying to initialize the Cart on the private backing field as you do, however when I do, I'm getting a Log In error "the tasks argument included a null value. Parameter task". I'm currently in a debug session trying to resolve it, mainly by doing a null check in "AddToCart", and whilst this is allowing me to login, I then get an error message saying "Items Collection must be empty before using ItemsSource".
    Still working on this on my own, but just wondering if you had any insight in this at all?

    • @NOCKSCITNEY
      @NOCKSCITNEY 2 ปีที่แล้ว

      Initial Investigation seems to indicate that the error is thrown when the "NotifyOfPropertyChange" is called within the "SET" on the "Cart" property. When I comment this out, it adds the item to the list, however it doesn't allow me to Initialize the BindingList on the backing field. I still have to use a "null check and initialize" within the AddToCart method

    • @NOCKSCITNEY
      @NOCKSCITNEY 2 ปีที่แล้ว

      UPDATE: So I've managed to get it working by doing the following in "AddToCart"
      - Do a null check on Cart and create a new instance if it's null
      - Add the item to Cart
      - Fire a "NotifyOfPropertyChange" form within AddToCart, which then updates the Cart List View.
      I'm not quite sure why the "NotifyOfProperyChange" isn't working in the property's SET, but I'll keep chipping away at it for now to see if I can find anything, but if anyone has any insight into this, I'd be greatful

    • @NOCKSCITNEY
      @NOCKSCITNEY 2 ปีที่แล้ว

      After a lengthy debugging session, I have managed to resolve the issue and it's now working as per your code. I'm guessing that I had a typo somewhere along the line, however I can't say where it was, but chipping away, and trying different things got me there in the end. Like most programmers know, walking away for a while and coming back to the problem helps more often than not.
      Sorry for the comment thread, and thanks once again for the amazing content you continue to put out the the community 😀

    • @IAmTimCorey
      @IAmTimCorey  2 ปีที่แล้ว +2

      I am glad you figured it out. Way to stick with it and debug the issue.

  • @ahmadaskar3360
    @ahmadaskar3360 4 หลายเดือนก่อน

    is it logical to just list all the products from the database ? what they are many products and admin wants to search a certain products, also what if products are categorized

    • @IAmTimCorey
      @IAmTimCorey  4 หลายเดือนก่อน +1

      It depends on the situation. In this situation, yes. Especially at a cash register. You don't want to make a database call every time a product is scanned. Besides, how many products can a business have? In most cases, that number is probably under 10,000. In larger cases, it might be upwards of 100,000 (A Walmart, on average, has 120,000 items). Your computer can easily handle that in memory. That means you can make one call and then cache the results for as long as you need them rather than multiple calls per person checking out.
      Having the data in memory means almost instant searches and no additional overhead for the SQL Server or the network.
      Now in the cases where this is not possible, you have a lot more work to do. You need to identify efficient ways to reduce your SQL calls. Maybe you put your most popular items in memory and only search for the others. Maybe you wait until all of the items are inputted and then search for all of them in one call. There are lots of ways to make things more efficient if you need to, but that's only when you get larger than Walmart that you need to consider it.

    • @ahmadaskar3360
      @ahmadaskar3360 4 หลายเดือนก่อน

      @@IAmTimCorey Thanks, tim

  • @LeopardLX
    @LeopardLX 5 ปีที่แล้ว

    Can someone explain why ItemQuantity textblock knows the actual quantity of items in stock? I don't understand the connection. When you type a number that's greater than the stock quantity, the field turns red.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      It is pulling that information from the item model, where it knows the quantity.

  • @KonradSchK
    @KonradSchK 5 ปีที่แล้ว

    Hey Tim.
    Can u make a tutorial where u demonstrate how to make a user page that gets ur user data like Firstname Lastname Age, Weight, etc, when u log in with Username and Password. Short. - Demonstrate how and what happens when U go from the login page to the Userpage when a Login is succesfully

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว

      I will add it to the list. Thanks for the suggestion.

  • @roostermaind6413
    @roostermaind6413 5 ปีที่แล้ว +2

    Tim, please increase the zoom on your code. If a line is too long just split it.

    • @IAmTimCorey
      @IAmTimCorey  5 ปีที่แล้ว +2

      I try to get a good balance. I'll see what I can do.

    • @roostermaind6413
      @roostermaind6413 5 ปีที่แล้ว +2

      @@IAmTimCorey Thank you, Tim. And, as always, thank you for the helpful content you put out here.
      I struggle to find any series as in-depth as yours.
      Other instructors just get into a concept, give a quick and easy example then toss it out the window.
      You really explore fully developing an application and mastering all the crucial aspects of a technology in your videos.

    • @harag9
      @harag9 5 ปีที่แล้ว

      @@IAmTimCorey That's the problem, where I find the code too large :) Difficult to find a good balance.

  • @SuperDre74
    @SuperDre74 4 ปีที่แล้ว

    Personally don't like the hack with the DisplayText, how it is displayed should be handled by the view itself. Better was to use a stackedpanel (horizontal) and use textbox for the QuantityInStock (and a textbox before and after to handle the ' (' and ')' (maybe there's a better way to do that but doesn't work.

    • @IAmTimCorey
      @IAmTimCorey  4 ปีที่แล้ว +1

      Not a hack, a method of creating a modified output. Yes, you could do it other ways but this way allows you to reuse the same text configuration multiple times, so it can be used consistently. Sure, you could do the same thing in the view but as you said, that would be messy and if you needed to do it in more than one place it would also be repetitive.

  • @DevDirge
    @DevDirge ปีที่แล้ว +1

    Loving this series and wish I would have found it years ago. Hopefully I can help others with the approach I used for updating the BindingList.
    The ListBox quantities will update correctly if the CartItemModel implements the INotifyPropertyChanged interface and invokes the event in the property setter.
    public class CartItemModel : INotifyPropertyChanged
    {
    private int _quantityInCart;
    public ProductModel Product { get; set; }
    public int QuantityInCart {
    get
    {
    return _quantityInCart;
    }
    set
    {
    _quantityInCart = value;
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(QuantityInCart)));
    }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    }

  • @于莉-d9h
    @于莉-d9h 2 ปีที่แล้ว

    Hi Tim
    This is my way to avoid remove then adding existing item to the cart display, just notify DisplayText when setting QuantityInCart:
    using Caliburn.Micro;
    namespace TRMDesktopUILibrary.Models
    {
    public class CartItemModel : PropertyChangedBase
    {
    public ProductModel Product { get; set; }
    private int quantityInCart;
    public int QuantityInCart
    {
    get { return quantityInCart; }
    set
    {
    quantityInCart = value;
    NotifyOfPropertyChange(() => DisplayText);
    }
    }
    public string DisplayText
    {
    get
    {
    return $"{Product.ProductName} ({QuantityInCart})";
    }
    }
    }
    }
    My idea is that CartItemModel is a view model. Am I right?
    🤔