0

モデルのプロパティへの単純な双方向データ バインディングが機能しません。問題を再現するために、Visual Studio 2013 で新しいプロジェクトを作成しました。つまり、.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));
            }
        }
    }
}

ナビゲートできないインターフェース

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 からビュー モデル インスタンスを取得し、ビュー モデルの依存関係が SimpleIoc によって注入され、コードがよりクリーンになるためです。

4

1 に答える 1

1

問題は、 の変更のみを通知することですPersonModel PersonViewModel は のプロパティの変更を通知する必要があります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 に答える