0

私は今MVVMを学んでいます。多くのチュートリアルやプロジェクトでViewとViewModelのみを使用しているのを見てきたので、少し混乱しました。これは私のコードです。

モデル :

public class StudentModel : PropertyChangedBase
{
    private String _firstName;
    public String FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            NotifyOfPropertyChange(() => FirstName);
        }
    }

    private Double _gradePoint;
    public Double GradePoint
    {
        get { return _gradePoint; }
        set
        {
            _gradePoint = value;
            NotifyOfPropertyChange(() => GradePoint);
        }
    }
}

見る :

<UserControl x:Class="MVVMLearningWithCaliburnMicro.Views.StudentView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:cal="http://www.caliburnproject.org">
    <Grid Width="525" Height="300" Background="Lavender">
        <DockPanel>
            <TextBlock HorizontalAlignment="Center" Text="Student Data"
                       DockPanel.Dock="Top" FontSize="20" />
            <StackPanel Orientation="Vertical" HorizontalAlignment="Center"
                        VerticalAlignment="Stretch"
                        Margin="0,8" DockPanel.Dock="Top">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="Name" FontSize="15" Margin="5,0" />
                    <TextBox Name="txtName" Text="{Binding Path=Student.FirstName}" Width="250" />
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="Grade" FontSize="15" Margin="5,0" />
                    <TextBox Name="txtGrade" Text="{Binding Path=Student.GradePoint}" Width="250" />
                </StackPanel>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0,5" HorizontalAlignment="Center"
                        VerticalAlignment="Bottom"
                        DockPanel.Dock="Bottom">
                <Button Name="btnSave" Width="100" Height="40"
                        cal:Message.Attach="SaveStudent">
                    <TextBlock Text="Save" FontSize="15" />
                </Button>
            </StackPanel>
        </DockPanel>
    </Grid>
</UserControl>

ビューモデル:

public class StudentViewModel
{
    public StudentModel Student { get; set; }

    public void SaveStudent()
    {
        MessageBox.Show(String.Format("Saved: {0} - ({1})", Student.FirstName, Student.GradePoint));
    }

    public StudentViewModel()
    {
        Student = new StudentModel { FirstName = "Tom Johnson", GradePoint = 3.7 };
    }

    private Boolean CanSaveStudent()
    {
        return Student.GradePoint >= 0.0 || Student.GradePoint <= 4.0;;
    }
}

Q: 1.はモデルに含まれている
ので、ガードプロパティを配置するにはどうすればよいですか? 2.(愚かな質問)私のMVVMパターンは正しい方向を向いていますか? NotifyOfPropertyChange()

4

4 に答える 4

2

1つの解決策は、PropertyChangedBaseからビューモデルを継承し、StudentModelのプロパティ変更をサブスクライブすることです。次に、guardメソッドを次のようにプロパティに変換します。

public class StudentViewModel: PropertyChangedBase
{
    public StudentModel Student { get; set; }

    public void SaveStudent()
    {
        MessageBox.Show(String.Format("Saved: {0} - ({1})", Student.FirstName, Student.GradePoint));
    }

    public StudentViewModel()
    {
        Student = new StudentModel { FirstName = "Tom Johnson", GradePoint = 3.7 };
        Student.PropertyChanged += delegate { NotifyOfPropertyChanged( () => CanSaveStudent)};
    }

    public Boolean CanSaveStudent
    {
        get 
        {
            return Student.GradePoint >= 0.0 || Student.GradePoint <= 4.0;
        }
    }
}

それがうまくいくことを願っています。

于 2012-06-09T21:17:05.687 に答える
1

通知イベントに存在する必要があります。view modelこれにより、からの変更が通信され、modelUIにプッシュされます。その逆も同様です。これは、MVVM設計ガイドラインに準拠しています。

特定のケースでは、そのままにするか、そのままにしておくことができますが、不要なものを削除するview modelか、通知機能を移動しますview model

于 2012-06-09T21:03:21.407 に答える
0

通知の変更はモデルに含まれている必要があります。これもバインドされているためです。基本的に、ビューモデルはオブジェクトのリストをロードし、ほとんどの場合にバインドされたコレクションをUIに提供する必要があります。上記の実装は、単一のオブジェクト(編集モードなど)を持つ詳細なパネルのように見えます。

要約すると。

ViewModel-INotifyPropertyChangeedインターフェイスを実装する必要がありますModel-INotifyPropertyChangeedインターフェイスを実装する必要があります

コマンド/ボタンを有効/無効にするには、コマンドバインディングを使用する必要があります。参照できるWPFとSilverlightのチュートリアルがあります。

http://tsells.wordpress.com/2010/06/23/command-binding-with-wpf-and-silverlight-net-4-0-with-mv-vm/

私はまた、このことを取り巻く過去数年間にいくつかのチュートリアルを作成しました。あなたが好きならそれらをチェックしてください....

http://tsells.wordpress.com/2011/02/08/using-reflection-with-wpf-and-the-inotifypropertychanged-interface/

http://tsells.wordpress.com/2010/06/02/wpf-model-view-viewmodel-mv-vm-example/

于 2012-06-09T23:31:51.233 に答える
0

わかりました、コードに結論がありますこれが
私のインスピレーションです

@tsells-3番目のリンクをありがとう

@john polvora-プロパティを指摘してくれてありがとう
重要:それは公共のプロパティでなければなりません

Caliburn.Microのガード句でガード句が起動しないエラー


そして、これが私のコードです。

モデル :

public class StudentModel
{
    public String FirstName { get; set; }
    public Double GradePoint { get; set; }
}

見る :

<UserControl x:Class="MVVMWithCMTwo.Views.StudentView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:cal="http://www.caliburnproject.org">
    <Grid Width="525" Height="300" Background="Lavender">
        <DockPanel>
            <TextBlock HorizontalAlignment="Center" Text="Student Data"
                       DockPanel.Dock="Top" FontSize="20" />
            <StackPanel Orientation="Vertical" HorizontalAlignment="Center"
                        VerticalAlignment="Stretch"
                        Margin="0,8" DockPanel.Dock="Top">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="Name" FontSize="15" Margin="5,0" />
                    <TextBox Name="txtName" Text="{Binding Path=StudentName}" Width="250" />
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="Grade" FontSize="15" Margin="5,0" />
                    <TextBox Name="txtGrade" Text="{Binding Path=StudentGrade}" Width="250" />
                </StackPanel>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0,5" HorizontalAlignment="Center"
                        VerticalAlignment="Bottom"
                        DockPanel.Dock="Bottom">
                <Button Name="btnSave" Width="100" Height="40"
                        cal:Message.Attach="SaveStudent">
                    <TextBlock Text="Save" FontSize="15" />
                </Button>
            </StackPanel>
        </DockPanel>
    </Grid>
</UserControl>

ビューモデル:

public class StudentViewModel : PropertyChangedBase
{
    public StudentModel Student { get; set; }

    public String StudentName
    {
        get { return Student.FirstName; }
        set
        {
            Student.FirstName = value;
            NotifyOfPropertyChange(() => Student.FirstName);
        }
    }

    public Double StudentGrade
    {
        get { return Student.GradePoint; }
        set
        {
            Student.GradePoint = value;
            NotifyOfPropertyChange(() => Student.GradePoint);
            NotifyOfPropertyChange(() => CanSaveStudent);
        }
    }

    public void SaveStudent()
    {
        MessageBox.Show(String.Format("Saved: {0} - ({1})", Student.FirstName, Student.GradePoint));
    }

    public StudentViewModel()
    {
        Student = new StudentModel { FirstName = "Tom Johnson", GradePoint = 3.7 };
    }

    public Boolean CanSaveStudent
    {
        get { return Student.GradePoint >= 0.0 && Student.GradePoint <= 4.0; }
    }
}
于 2012-06-10T05:29:07.767 に答える