0

Простая двусторонняя привязка данных к свойству модели не работает, чтобы воспроизвести проблему, я создал новый проект в Visual Studio 2013, т. Е. С шаблоном Blank App (Universal Apps) с .NET. рамки 4,5Проблема с привязкой данных Universal Windows Apps 8.1

Project folders and files

модель

namespace UWP.MVVM.Models 
{ 
    public class PersonModel 
    { 
     public int Id { get; set; } 

     public string FirstName { get; set; } 

     public string LastName { get; set; } 
    } 
} 

базовая модель вид

namespace UWP.MVVM.Core 
{ 
    using System.ComponentModel; 
    using System.Runtime.CompilerServices; 

    public class VMBase : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     public void NotifyPropertyChanged([CallerMemberName] string propertyName = "") 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

INavigable интерфейс

namespace UWP.MVVM.Core 
{ 
#if WINDOWS_PHONE_APP 
    using Windows.Phone.UI.Input; 
#endif 

    public interface INavigable 
    { 
     void Activate(object parameter); 

     void Deactivate(object parameter); 

#if WINDOWS_PHONE_APP 
     void BackButtonPressed(BackPressedEventArgs e); 
#endif 
    } 
} 

Основной вид вид модели

namespace UWP.MVVM.ViewModels 
{ 
    using UWP.MVVM.Core; 
    using UWP.MVVM.Models; 
#if WINDOWS_PHONE_APP 
    using Windows.Phone.UI.Input; 
#endif 

    public class MainViewModel : VMBase, INavigable 
    { 
     private PersonModel person; 

     public MainViewModel() 
     { 
      this.Person = new PersonModel(); 
     } 

     public PersonModel Person 
     { 
      get 
      { 
       return this.person; 
      } 
      set 
      { 
       if (value == this.person) 
       { 
        return; 
       } 

       this.person = value; 
       this.NotifyPropertyChanged(); 
      } 
     } 

     public void Activate(object parameter) 
     { 
      this.Person.FirstName = "Gerrard"; 
     } 

     public void Deactivate(object parameter) 
     { 
     } 

#if WINDOWS_PHONE_APP 
     public void BackButtonPressed(BackPressedEventArgs e) 
     { 
     } 
#endif 
    } 
} 

Главная страница

<Page 
    x:Class="UWP.MVVM.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:UWP.MVVM" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:vm="using:UWP.MVVM.ViewModels" 
    mc:Ignorable="d" 
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <!--<Page.DataContext> 
     <vm:MainViewModel/> 
    </Page.DataContext>--> 

    <Grid Margin="24,24"> 
     <TextBox Header="First Name" 
       Text="{Binding Person.FirstName}"/> 
    </Grid> 
</Page> 

Основной код страницы за

namespace UWP.MVVM 
{ 
    using UWP.MVVM.Core; 
#if WINDOWS_PHONE_APP 
    using Windows.Phone.UI.Input; 
#endif 
    using Windows.UI.Xaml.Controls; 
    using Windows.UI.Xaml.Navigation; 
    using UWP.MVVM.ViewModels; 

    /// <summary> 
    /// An empty page that can be used on its own or navigated to within a Frame. 
    /// </summary> 
    public sealed partial class MainPage : Page 
    { 
     public MainPage() 
     { 
      this.InitializeComponent(); 

      this.NavigationCacheMode = NavigationCacheMode.Required; 
      this.DataContext = new MainViewModel(); 
     } 

     /// <summary> 
     /// Invoked when this page is about to be displayed in a Frame. 
     /// </summary> 
     /// <param name="e">Event data that describes how this page was reached. 
     /// This parameter is typically used to configure the page.</param> 
     protected override void OnNavigatedTo(NavigationEventArgs e) 
     { 
      base.OnNavigatedTo(e); 
      var navigableViewModel = this.DataContext as INavigable; 
      if (navigableViewModel != null) 
      { 
       navigableViewModel.Activate(e.Parameter); 
      } 

#if WINDOWS_PHONE_APP 
      HardwareButtons.BackPressed += HardwareButtons_BackPressed; 
#endif 
     } 

     protected override void OnNavigatedFrom(NavigationEventArgs e) 
     { 
      base.OnNavigatedFrom(e); 
      var navigableViewModel = this.DataContext as INavigable; 
      if (navigableViewModel != null) 
      { 
       navigableViewModel.Deactivate(e.Parameter); 
      } 

#if WINDOWS_PHONE_APP 
      HardwareButtons.BackPressed -= HardwareButtons_BackPressed; 
#endif 
     } 

#if WINDOWS_PHONE_APP 
     private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) 
     { 
      var navigableViewModel = this.DataContext as INavigable; 
      if (navigableViewModel != null) 
      { 
       navigableViewModel.BackButtonPressed(e); 
      } 
     } 
#endif 
    } 
} 

Я попытался использовать Mode = TwoWay в TextBox, но он не работает, но когда я устанавливаю DataContext в xaml вместо кода, то привязка данных работает даже без свойства Mode = TwoWay.

Я хочу установить DataContext в код за файлом, как в реальном проекте, где у меня эта проблема, я использую библиотеки MVVM-light вместе с контейнером SimpleIoc, поэтому я хочу получить экземпляр модели представления из SimpleIoc и установить DataContext, потому что зависимости модели представления вводятся с помощью SimpleIoc, и код будет намного чище.

+0

Тег ** UWP ** следует использовать только если речь идет о разработке для универсальной платформы Windows через Windows, 10. Но вы похоже, использует VS 2013, который не поддерживает разработку UWP. –

+0

Хорошо, что это должны быть универсальные приложения для Windows, я ошибался –

ответ

1

Проблема: вы изведете о замене PersonModel Person. ViewModel необходимо уведомить об изменении свойства от PersonModel.

Поскольку вы используете MVVM Light, изменить свою модель на:

public class PersonModel : ObservableObject 
{ 
    public int Id { get; set; } 

    string _FirstName = ""; 
    public string FirstName { 
     get { 
      return _FirstName; 
     } 
     set { 
      Set(ref _FirstName, value); 
     } 
    } 

    public string LastName { get; set; } 
} 
+0

Можно ли реализовать INotifyPropertyChanged как на ViewModel, так и на модели здесь в этом контексте, или мне нужно реализовать его только на модели? –

+0

MVVM Light имеет ObservableObject для использования в модели и BaseViewModel для ViewModel. Оба могут использоваться для уведомления PropertyChanged. Если вы хотите, чтобы модель была чистой, вы можете повысить свойство PropertyChanged для свойства Person и ViewModel: 'NotifyPropertyChanged (« Person.FirstName »);' Пожалуйста, примите мой ответ, если это поможет :) – thang2410199

Смежные вопросы