locked
Entity Framework MVVM, Insert Data into Database RRS feed

  • Question

  • This question is mainly aimed for Andy ONeill, as i'm basing my code on his guide. 

    I have read and understood your code best I can. From what I can tell when fetching data to display:

    1. First of all create a ProductVM, this creates an instance of the Product Class and sets up the metadata for validation ect.
    2. Then each ProductVM is added to an ObservableCollection which is binded to. 

    This makes sense, however I want to Insert some data, you have the starting for that but seems you never finished it, could you tell me if i'm wrong here:

    1. Bind to a list of commands, these CommandMessages are sent to the CrudVMBase where the method is defined.
    2. In this case InsertNew() is used, this method then initializes a new ProductVM.
    3. This then gets passed to EditVM which passes the Product Class instance to editEntity within CrudVMBase.

    This is where i'm getting kind of lost, could you explain a bit more on where it goes from there. 

    Also, how would I go about putting my data in an instance (in my case) user class? I originally binded to some properties in an instance of a class, however i'm not sure this is the correct way now. Some of the properties are filled in using code, not the user. 

    Of course I would have to send the password using the command parameter as well as you can't bind to it. Below is the code I currently have, but I believe this is wrong.

    public class Register : NotifyUIBase
        {
    
            public string ClearPassword { get; set; }
            public string Salt { get; set; } //Auto - Generated using code
            public DateTime DateCreated { get; set; } //Auto - Todays date
            public Visibility Result { get; set; } //Auto - Changed if there are no errors
    
            public RelayCommand RegisterCommand { get; set; }
            public Register()
            {
                Result = Visibility.Hidden;
                RegisterCommand = new RelayCommand(RegisterExecute);
            }
            private void RegisterExecute()
            {
                Salt = Common.Security.KeyGenerator.GetUniqueKey(64);
                DateCreated = DateTime.Now;
    
            }
        }

    Edit:

    Looking more into the code I see that the Commands you define on MainWindowViewModel are pretty vital in their setup. Due to my Views having many different Buttons which will need different commands, and not always being Menu Bar style, how could I setup a button on it's own without using a List? Could I just do the following and have the button Bind to it?

    public CommandVM RegisterCommandButton { get; set; } = new CommandVM { CommandDisplay = "Register", IconGeometry = App.Current.Resources["InsertIcon"] as Geometry, Message = new CommandMessage { Command = CommandType.Insert } };

    • Edited by martynball Monday, January 25, 2016 8:36 PM
    Monday, January 25, 2016 8:12 PM

Answers

  • I just successfully added a customer using this version:

    https://gallery.technet.microsoft.com/WPF-Entity-Framework-MVVM-78cdc204

    You click the big plus on the edit command menu.

    Fill in the stuff.

    Click the green floppy disk button.

    Then of course you have to click the red one to exit....

    But it's added.

    From CustomerViewModel.

            protected override void InsertNew()
            {
                EditVM = new CustomerVM();
                IsInEditMode = true;
            }

    and

            protected override void CommitUpdates()
            {
                if (EditVM.TheEntity.IsValid())
                {
                    if (EditVM.IsNew)
                    {
                        EditVM.IsNew = false;
                        Customers.Add(EditVM);
                        db.Customers.Add(EditVM.TheEntity);
                        UpdateDB();
                    }
                    else if (db.ChangeTracker.HasChanges())
                    {
                        UpdateDB();
                    }
                    else
                    {
                        ShowUserMessage("No changes to save");
                    }
                }
                else
                {
                    ShowUserMessage("There are problems with the data entered");
                }
            }

    updatedb:

            private void UpdateDB()
            {
                try
                {
                    db.SaveChanges();
                    ShowUserMessage("Database Updated");
                }
                catch (Exception e)
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        ErrorMessage = e.InnerException.GetBaseException().ToString();
                    }
                    ShowUserMessage("There was a problem updating the database");
                }
    
            }

    The actual typing in of data is done in the overlay which is a templated control.

    If you look at customerview you can see it there because it's not hidden by default.

    The customerview contentcontrol:

            <ContentControl Template="{StaticResource EditPopUp}">
                    <ScrollViewer  VerticalScrollBarVisibility="Auto">
                    <ItemsControl>
                            <spt:EditRow LabelFor="Name:" >
                                <TextBox Text="{Binding  EditVM.TheEntity.CustomerName, 
                                    UpdateSourceTrigger=PropertyChanged,  
                                    NotifyOnSourceUpdated=True,
                                    NotifyOnValidationError=True,
                                    Mode=TwoWay}"  />
                            </spt:EditRow>
    
                            <spt:EditRow LabelFor="Address:" >
                                <TextBox Text="{Binding EditVM.TheEntity.Address1, 
                                                        UpdateSourceTrigger=PropertyChanged, 
                                                        NotifyOnSourceUpdated=True,
                                                        NotifyOnValidationError=True,
                                                        Mode=TwoWay}"  />
                            </spt:EditRow>
    
                            <spt:EditRow >
                                <TextBox Text="{Binding EditVM.TheEntity.Address2, 
                                                        UpdateSourceTrigger=PropertyChanged,
                                                        NotifyOnSourceUpdated=True,
                                                        NotifyOnValidationError=True,
                                                        Mode=TwoWay}"  />
                            </spt:EditRow>
    
                            <spt:EditRow >
                                <TextBox Text="{Binding EditVM.TheEntity.Address3, 
                                UpdateSourceTrigger=PropertyChanged,  
                                NotifyOnSourceUpdated=True,
                                NotifyOnValidationError=True,
                                Mode=TwoWay}"   />
                            </spt:EditRow>
    
                            <spt:EditRow LabelFor="Town/City:" >
                                <TextBox Text="{Binding EditVM.TheEntity.TownCity, 
                                            UpdateSourceTrigger=PropertyChanged,  
                                            NotifyOnSourceUpdated=True,
                                            NotifyOnValidationError=True,
                                            Mode=TwoWay}" />
                            </spt:EditRow>
    
                            <spt:EditRow LabelFor="Post Code:" >
                                <TextBox Text="{Binding EditVM.TheEntity.PostCode,  
                                            UpdateSourceTrigger=PropertyChanged,  
                                            NotifyOnSourceUpdated=True,
                                            NotifyOnValidationError=True,
                                            Mode=TwoWay}"   />
                            </spt:EditRow>
    
                            <spt:EditRow LabelFor="Credit Limit:" >
                                <TextBox 
                                x:Name="CreditLimit"
                                Text="{Binding   EditVM.TheEntity.CreditLimit, 
                                StringFormat={}{0:C0}, 
                                UpdateSourceTrigger=PropertyChanged,  
                                NotifyOnSourceUpdated=True,
                                NotifyOnValidationError=True,
                                Mode=TwoWay}" />
                            </spt:EditRow>
    
                            <spt:EditRow LabelFor="Outstanding Amount:">
                                <!-- Outstanding payments are calculated rather than entered -->
                                <TextBox Text="{Binding   EditVM.TheEntity.Outstanding, 
                                    StringFormat={}{0:C0}}"  />
                            </spt:EditRow>
                        </ItemsControl>
                    </ScrollViewer>
    
          </ContentControl>

    Dictionary1 contains the template that surrounds that with a panel and gives you the exit and save buttons as well as a list of any errors.

    The top of that is:

        <ControlTemplate x:Key="EditPopUp" TargetType="ContentControl">
            <ControlTemplate.Resources>
                <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource ErrorToolTip}">
                    <Setter Property="HorizontalAlignment" Value="Stretch"/>
                </Style>
            </ControlTemplate.Resources>


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles


    Monday, January 25, 2016 8:36 PM