wpf mvvm从不同窗口填充viewmodel中的模型数据对象

时间:2017-05-10 03:46:17

标签: c# wpf mvvm

我正在创建一个简单的MVVM应用程序,以及它的功能,

1)在阅读json文件后,在数据网格中显示详细信息。

2)将新记录添加到集合中并保存json文件。

我的问题是在MainWindow中按下Add按钮我打开一个AddContacts窗口,其中有一个Add按钮。现在,当在AddContacts窗口中按下Add按钮时,如何获取Contacts对象数据,以便我可以添加到ContactListViewModel中的ContactsList。 AddContact Window和MainWindow数据上下文都是ContactListViewModel。 通常我会在ContactListViewModel的AddWindow中为add按钮添加另一个Command。但请帮我填充模型数据。

所以我创建了一个模型如下;

public class Contacts:INotifyPropertyChanged
{

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            NotifyPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            NotifyPropertyChanged("LastName");
        }
    }

    private string _dateOfBirth;
    public string DateOfBirth
    {
        get { return _dateOfBirth; }
        set
        {
            _dateOfBirth = value;
            NotifyPropertyChanged("DateOfBirth");
        }
    }
    private string _weight;
    public string Weight
    {
        get { return _weight; }
        set
        {
            _weight = value;
            NotifyPropertyChanged("Weight");
        }
    }
    private string _height;
    public string Height
    {
        get { return _height; }
        set
        {
            _height = value;
            NotifyPropertyChanged("Height");
        }
    }
    private string _phone;
    public string Phone
    {
        get { return _phone; }
        set
        {
            _phone = value;
            NotifyPropertyChanged("Phone");
        }
    }



    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

现在我的视图模型如下;

    public class ContactListViewModel
    {
        private ObservableCollection<Contacts> _contactsCollection;
        public ObservableCollection<Contacts> ContactsCollection
        {
            get { return _contactsCollection; }
            set { _contactsCollection = value; }
        }

        private RelayCommand _addCommand;
        public ICommand AddCommand
        {
            get
            {
                if (_addCommand == null)
                {
                    _addCommand = new RelayCommand(param => this.OpenAddWindow());
                }
                return _addCommand;
            }
        }

        private void OpenAddWindow()
        {
            AddContact contact = new AddContact();
            contact.DataContext = this;
            contact.ShowDialog();
        }

        public ContactListViewModel()
        {

            //As discussed below using a thread.
            Thread th = new Thread(new ThreadStart(CreateSampleContacts));
            th.Start();

        }



        //Im hardcoding some contacts but I want to remove the hardcoding and 
 //add data thats coming from AddWindow
        public void CreateSampleContacts()
        {
            List<Contacts> contactsList = new List<Contacts>();
            contactsList.Add(new Contacts
            {
                FirstName = "Nikhil",
                LastName = "ANS",
                DateOfBirth = "07/12/1989",
                Weight = "184 lbs",
                Height = "6.0 feet",
                Phone = "805-251-1015"
            });

            contactsList.Add(new Contacts
            {
                FirstName = "Sam",
                LastName = "B",
                DateOfBirth = "04/10/1991",
                Weight = "174 lbs",
                Height = "5.10 feet",
                Phone = "800-800-8000"
            });

            contactsList.Add(new Contacts
            {
                FirstName = "Henry",
                LastName = "K",
                DateOfBirth = "05/06/1988",
                Weight = "184 lbs",
                Height = "6.4 feet",
                Phone = "408-408-4088"
            });

            if (contactsList.Count > 0)
            {
                try
                {
                    CreateJsonandWrite(contactsList);
                }
                catch(Exception ex)
                {
                    System.Windows.MessageBox.Show(ex.Message);
                }
             }
        }

        public async void CreateJsonandWrite(List<Contacts> allContacts)
        {
            string json = JsonConvert.SerializeObject(allContacts);
            await WriteToFile(json);
        }

        public Task WriteToFile(string json)
        {
            string path = "~/Contacts.json";
            return WriteTextToFileAsync(path, json);
        }

       //Asynchronosly writing data to the file
        public async Task WriteTextToFileAsync(string filePath, string text)
        {
            byte[] encodedText = Encoding.Unicode.GetBytes(text);

            using (FileStream sourceStream = new FileStream(filePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true))
            {
                await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
            };
        }
    }

主窗口

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0">
            <Button Height="25" Width="80">Add</Button>
            <Button Height="25" Width="80">Delete</Button>
        </StackPanel>

        <DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding ContactsCollection}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding DateOfBirth}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding Weight}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding Height}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding Phone}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

AddWindow

<Grid HorizontalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <TextBlock>First Name : </TextBlock>
            <TextBox Margin="20,0,0,0" Height="25" Width="120" Text="{Binding FirstName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="1">
            <TextBlock>Last Name :</TextBlock>
            <TextBox Margin="20,0,0,0" Height="25" Width="120" Text="{Binding LastName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="2">
            <TextBlock>Date of Birth :</TextBlock>
            <DatePickerTextBox Height="25" Width="120" Margin="10,0,0,0" Text="{Binding DateOfBirth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,StringFormat='dd/mm/yyyy'}">

            </DatePickerTextBox>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="3">
            <TextBlock>Width :</TextBlock>
            <TextBox Margin="45,0,0,0" Height="25" Width="120" Text="{Binding Weight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="4">
            <TextBlock>Height :</TextBlock>
            <TextBox Margin="42,0,0,0" Height="25" Width="120" Text="{Binding Height,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="5">
            <TextBlock>Phone :</TextBlock>
            <TextBox Margin="44,0,0,0" Height="25" Width="120" Text="{Binding Phone,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <Button Grid.Row="6" Margin="45">Add</Button>

//按下此添加按钮后,我想获取ContactList对象中的// ContactListViewModel中的数据。         

3 个答案:

答案 0 :(得分:0)

要将数据从子窗口传递到父窗口,您需要按照步骤

进行操作
  1. 在添加按钮中,单击子窗口的事件添加 DialogResult = true
  2. 在ParentWindow中将openAddWindow方法修改为

    private void OpenAddWindow()
    {
        AddContact contact = new AddContact();
        contact.DataContext = this;
        if(contact.ShowDialog() == true)
        {
             //here i have just given messagebox here you can fetch the data membersof AddContact window
             MessageBox.Show(contact.VariableAssumed);
             //On add button click in childwindow You can save your new contact in Contacts object(newContact) 
             //and you can retrieve the newContact here and add it to your Contact list present in parentwindow as below
             contactList.Add(contact.newContact);
        }
    }
    

答案 1 :(得分:0)

我正在尝试制作您发布的类的示例。希望这有帮助

AddContact类

class AddContact
{
   ....
   public Contacts newContact{get;set;}
   public AddContact()
   {
       newContact = new Contacts();
   }

   private void  OnAddButtonClicked()
   {
      newContact.FirstName = "Abc";//just i am taking abc asexample you fetch data from the textbox controls
      newContact.LastName = "Abc";
      .....
      //fill all the data members
      DialogResult = true;
      this.close();
   }
}

ContactListViewModel类

class ContactListViewModel 
{
     .....
     private ObservableCollection<Contacts> _contactsCollection;
     private void OpenAddWindow()
     {
         AddContact contact = new AddContact();
         contact.DataContext = this;
         if(contact.ShowDialog() == true)
         {
              _contactsCollection.Add(contact.newContact);
         }
     } 
}

答案 2 :(得分:0)

我很惊讶正确答案没有出现在这里。

我会试着解释你如何继续。

首先,您需要在应用程序的运行时间内使用能够包含所有引用的ViewModel的内容。

下载并安装MVVM Toolkit软件包nuget。

之后,尝试使用ViewModelLocator:

public class ViewModelLocator
{
    /// <summary>
    /// Initializes a new instance of the ViewModelLocator class.
    /// </summary>
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<ContactListViewModel>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public static ContactListViewModel ContactListVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<ContactListViewModel>();
        }
    }

    public static void CleanContactList()
    {
        SimpleIoc.Default.Unregister<ContactListViewModel>();
        SimpleIoc.Default.Register<ContactListViewModel>();
    }

    public static MainViewModel MainVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public static void CleanMain()
    {
        SimpleIoc.Default.Unregister<MainViewModel>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public static void Cleanup()
    {
        CleanMain();
        CleanContactList();
    }
}

以下是a link,可让您正确设置ViewModelLocator。

之后,无论您在代码中的任何位置,都可以通过 ViewModelLocator 中的静态属性调用任何ViewModel,并将任何属性设置到其中。