Проблема привязки данных к универсальным приложениям Windows 8.1
Простая двусторонняя привязка данных к свойству модели не работает, чтобы воспроизвести проблему, я создал новый проект в Visual Studio 2013, т. Е. С шаблоном Blank App (Universal Apps) с.NET Framework 4.5.
Модель
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, и код будет намного чище.
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; }
}