简体   繁体   中英

Entity Framework Field Is Required (MVVM)

I have been having this issue and have been trying to figure out for the past few days, I set up a second test project as my first project is too big to try and nail this down. I'm still fairly new to mvvm so I'm still learning. Whenever I try to save a field using Entity it starts complaining the FirstName field is required, I sort of nailed down the issue to being apart of something with the button because whenever I move the button into the same UserControl as the textbox it will save. The TabControl in the MainWindow has a UserControl for each tab and each one has their own respective ViewModel and then the TabControl itself has a ViewModel.

MainWindow Just contains the button and the tab control

    <Window.Resources>
        <vm:TabControlViewModel x:Key="tab"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource tab}">
        <TabControl Margin="10"
                    Width="500"
                    Height="500">
            <TabItem Header="Test Tab 1">
                <custom:TabOneUserControl/>
            </TabItem>
            <TabItem Header="Test Tab 2">
                <custom:TabTwoUserControl/>
            </TabItem>
        </TabControl>

        <Button Content="Save"
                Width="120"
                Height="50" 
                Margin="1114,604,41,38.5"
                Command="{Binding SaveCommand}"/>
    </Grid>

TabOneUserControl Contains a textbox and label

<UserControl.Resources>
        <vm:TabOneUserControlViewModel x:Key="vm"/>
    </UserControl.Resources>
    <Grid DataContext="{StaticResource vm}">
        <StackPanel VerticalAlignment="Center">
            <Label Content="First Name"
                   HorizontalAlignment="Center"/>
            <TextBox Width="250"
                     Height="50"
                     Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>
</UserControl>

TabTwoUserControl Contains a textbox and label

    <UserControl.Resources>
        <vm:TabTwoUserControlViewModel x:Key="vm"/>
    </UserControl.Resources>
    <Grid DataContext="{StaticResource vm}">
        <StackPanel VerticalAlignment="Center">
            <Label Content="Last Name"
                   HorizontalAlignment="Center"/>
            <TextBox Width="250"
                     Height="50"
                     Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>
</UserControl>

TabControlViewModel For the tab control

public class TabControlViewModel
    {
        public SaveCommand SaveCommand { get; set; }
        private TabOneUserControlViewModel tabOneUserControl;
        private TabTwoUserControlViewModel tabTwoUserControl;

        public TabControlViewModel()
        {
            tabOneUserControl = new TabOneUserControlViewModel();
            tabTwoUserControl = new TabTwoUserControlViewModel();
            SaveCommand = new SaveCommand(this);
        }

        public void SaveInformation()
        {
            using (TestDbEntities test = new TestDbEntities())
            {
                test.FNs.Add(new FN
                {
                    FirstName = tabOneUserControl.FirstName
                });

                test.LNs.Add(new LN
                {
                    LastName = tabTwoUserControl.LastName
                });

                try
                {
                    test.SaveChanges();
                    Debug.Print("SAVED CHANGES!");
                }
                catch (DbEntityValidationException ex)
                {
                    foreach (var validationErrors in ex.EntityValidationErrors)
                    {
                        foreach (var validationError in validationErrors.ValidationErrors)
                        {
                            Trace.TraceInformation(
                                  "Class: {0}, Property: {1}, Error: {2}",
                                  validationErrors.Entry.Entity.GetType().FullName,
                                  validationError.PropertyName,
                                  validationError.ErrorMessage);
                        }
                    }
                }
            }
        }
    }

TabOneUserControlViewModel For the first tab user control

public class TabOneUserControlViewModel : INotifyPropertyChanged
    {
        private string firstName;

        public event PropertyChangedEventHandler PropertyChanged;

        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                OnPropertyChanged("FirstName");
            }
        }
        public TabOneUserControlViewModel()
        {

        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

TabTwoUserControlViewModel For the second tab user control

public class TabTwoUserControlViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private string lastName;

        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                OnPropertyChanged("LastName");
            }
        }

        public TabTwoUserControlViewModel()
        {

        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

Thanks to everyone in the comments for your suggestions, Nawed's comment nailed it perfectly for what I was doing wrong. Here is the final code changes I made:

TabControlViewModel Removed the fields and made them into properties

public class TabControlViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public SaveCommand SaveCommand { get; set; }

        public TabOneUserControlViewModel TabOneUserControl { get; set; }

        public TabTwoUserControlViewModel TabTwoUserControl { get; set; }

        public TabControlViewModel()
        {
            TabOneUserControl = new TabOneUserControlViewModel();
            TabTwoUserControl = new TabTwoUserControlViewModel();
            SaveCommand = new SaveCommand(this);
        }

        public void SaveInformation()
        {
            using (TestDbEntities test = new TestDbEntities())
            {
                test.FNs.Add(new FN
                {
                    FirstName = TabOneUserControl.FirstName
                });

                test.LNs.Add(new LN
                {
                    LastName = TabTwoUserControl.LastName
                });

                try
                {
                    test.SaveChanges();
                    Debug.Print("SAVED CHANGES!");
                }
                catch (DbEntityValidationException ex)
                {
                    foreach (var validationErrors in ex.EntityValidationErrors)
                    {
                        foreach (var validationError in validationErrors.ValidationErrors)
                        {
                            Trace.TraceInformation(
                                  "Class: {0}, Property: {1}, Error: {2}",
                                  validationErrors.Entry.Entity.GetType().FullName,
                                  validationError.PropertyName,
                                  validationError.ErrorMessage);
                        }
                    }
                }
            }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

TabOneUserControl Removed the static resource from the grid and replaced it with a regular binding and then changed the binding in the Text element, this was the same thing I did in the second user control so I will negate posting the second UserControl:

<Grid DataContext="{Binding TabOneUserControl}">
        <StackPanel VerticalAlignment="Center">
            <Label Content="First Name"
                   HorizontalAlignment="Center"/>
            <TextBox Width="250"
                     Height="50"
                     Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM