Привязка WPF не работает при привязке к объекту в модели представления - PullRequest
0 голосов
/ 08 июня 2019

Я создаю список контактов в WPF, используя MVVM. Когда пользователь добавляет контакт, представление NewContact будет в окне. Текстовые поля должны быть связаны с объектом с именем NewContact в NewContactViewModel. DataContext установлен в AppViewModel, который является моделью центрального представления, но в AppViewModel есть модель представления NewContact, называемая NewContactVM. Поскольку я подключаюсь непосредственно к этой виртуальной машине, я ожидаю, что она будет работать. Вот NewContact.xaml:

<Window x:Class="ContactList.Windows.NewContact"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ContactList"
        xmlns:vm="clr-namespace:ContactList.ViewModels"
        xmlns:v="clr-namespace:ContactList.Views"
        mc:Ignorable="d"
        Title="NewContact" Height="450" Width="400">

    <Window.DataContext>
        <local:AppViewModel/>
    </Window.DataContext>
    <Grid>
        <Border Padding="10">
            <StackPanel>

                <!-- Contact Entries-->
                <!-- Contact Name -->
                <TextBlock Text="Contact Name" Margin="5 10" />
                <TextBox Text="{Binding NewContactVM.NewContact.Name,
                    FallbackValue=NULL, Mode=TwoWay}" 
                          Padding="2" Margin="5 0" ></TextBox>
                <!-- Contact Number -->
                <TextBlock Text="Contact Number" Margin="5 10" />
                <TextBox Text="{Binding NewContactVM.NewContact.PhoneNumber, FallbackValue=NULL, Mode=TwoWay}"
                     Padding="2" Margin="5 0"></TextBox>
                <!-- Contact Email -->
                <TextBlock Text="Contact Email" Margin="5 10" />
                <TextBox Text="{Binding NewContactVM.NewContact.Email, FallbackValue=NULL, Mode=TwoWay}" 
                     Padding="2" Margin="5 0"></TextBox>

                <!-- Add Contact Button -->
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Button x:Name="AddContactButton"  Grid.Column="1" Content="Add Contact" 
                            Command="{Binding NewContactVM.SaveContactCommand}" Margin="10"/>
                </Grid>
            </StackPanel>
        </Border>
    </Grid>
</Window>

Однако всякий раз, когда добавляется NewContact, это всегда значение NULL. Это NewContactViewModel:

    public class NewContactViewModel : ObservableObject
    {
        public ObservableCollection<Contact> Contacts { get; set; }
        private List<Contact> _contacts;

        private Contact _newContact;
        public Contact NewContact
        {
            get { return _newContact; }
            set { OnPropertyChanged(ref _newContact, value); }
        }

        public ICommand OpenNewContactWindowCommand { get; private set; }
        public ICommand SaveContactCommand { get; private set; }

        private IContactDataService _dataService;


        public NewContactViewModel(IContactDataService dataService)
        {
            _dataService = dataService;
            _contacts = dataService.GetContacts().ToList();
            OpenNewContactWindowCommand = new RelayCommand(showNewContact);
            SaveContactCommand = new RelayCommand(Save);
        }

        private void showNewContact()
        {
            NewContact newContact = new NewContact();
            newContact.Show();
        }

        private void Save()
        {
            Contacts = new ObservableCollection<Contact>(_contacts);
            _dataService.Save(_contacts);
            Contacts.Add(NewContact);
            _contacts.Add(NewContact);

        }
    }

Поскольку значение всегда равно null, привязка не должна происходить, но я не могу понять, почему, я новичок в архитектуре MVVM. (Для справки объект «Контакт» - это просто пользовательский объект с открытыми строками для имен с использованием методов получения и установки).

1 Ответ

0 голосов
/ 09 июня 2019

Если я правильно вас понимаю, ваш код работает следующим образом:

  1. Ваша основная ViewModel называется AppViewModel
  2. В вашей AppViewModel У вас есть NewContactVM, который является классом NewContactViewModel
  3. В вашем NewContactVM у вас есть метод showNewContact, в котором вы создаете новое окно NewContact.
  4. Новый экземпляр окна NewContact создает новый (возможно, неинициализированный) AppViewModel.Теперь у вас есть совершенно новый второй AppViewModel, благодаря этому коду.

    <Window.DataContext>
        <local:AppViewModel/>
    </Window.DataContext>
    

Исправлено:

Поскольку все ваши привязки ссылаются на AppViewModel.NewContactVM, вы должны просто изменитьтекстовый текст нового окна.

  1. Сначала удалите этот код из XAML

    <Window.DataContext>
        <local:AppViewModel/>
    </Window.DataContext>
    
  2. Затем измените метод showNewContact, чтобы установить DataContext

    private void showNewContact()
    {
        NewContact newContact = new NewContact();
        newContact.DataContext = this;
        newContact.Show();
    }
    

Обновление:

Если ваше свойство NewContact имеет значение null, это потому, что оно нигде не инициализировано.

Попробуйте изменить это:

private Contact _newContact;
public Contact NewContact
{
    get { return _newContact; }
    set { OnPropertyChanged(ref _newContact, value); }
}

к этому

private Contact _newContact = new Contact();
public Contact NewContact
{
    get { return _newContact; }
    set { _newContact = value; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...