0

简单的双向数据绑定到模型的属性不起作用,为了重现该问题,我在 Visual Studio 2013 中创建了一个新项目,即使用带有 .NET 框架 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
    }
}

我尝试在 TextBox 上使用 Mode=TwoWay 并且它不起作用,但是当我在 xaml 中设置 DataContext 而不是后面的代码时,即使没有 Mode=TwoWay 属性,数据绑定也可以工作。

我想在文件后面的代码中设置 DataContext,就像在我遇到这个问题的实际项目中一样,我正在使用 MVVM-light 库及其 SimpleIoc 容器,所以我想从 SimpleIoc 获取视图模型实例并设置DataContext,因为视图模型依赖是由 SimpleIoc 注入的,代码会干净很多。

4

1 回答 1

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; }
}
于 2016-06-05T10:59:09.647 回答