8

ViewModel間で通信する方法を理解する必要があります。私はMVVMを初めて使用するので、親切にしてください。

これはばかげた例です

クラス定義(ParentViewModelでChild.PropertyChangedイベントをフックしたと仮定します):

public class ParentViewModel : ViewModelBase
{
    public ChildViewModel Child { get; set; }
}

public class ChildViewModel : ViewModelBase
{
    String _FirstName;
    public String FirstName 
    {
        get { return _FirstName; }
        set
        {
            _FirstName = value;
            OnPropertyChanged("FirstName");
        }
    }
}

これがリソース辞書に表示されるものです

<DataTemplate DataType="{x:Type vm:ParentViewModel}">
    <vw:ParentView/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:ChildViewModel}">
    <vw:ChildView/>
</DataTemplate>

およびChildViewのコードビハインド:

public partial class ChildView : UserControl
{
    public QueueView()
    {
        InitializeComponent();
        DataContext = new ChildViewModel();
    }
}

明らかな問題は、ChildViewが(DataTemplateからの選択を介して)インスタンス化されると、新しいChildViewModelクラスが作成され、ParentViewModelがそれにアクセスできないことです。

では、ビューのDataContextを、DataTemplateが選択される原因となった元のViewModelにインスタンス化するにはどうすればよいですか?

明らかな修正は、ChildViewModelのプロパティをParentViewModelにマージすることですが、再利用するために分離したいと思います。

答えは些細なことだと確信しています。それが何であるかを知りたいだけです。:)

前もって感謝します。

4

3 に答える 3

8

次の行を削除するだけです。

DataContext = new ChildViewModel();

ビューのDataContextは WPF によって自動的に設定されます。DataTemplates常にテンプレートのデータ (この場合は ViewModel) にデータ コンテキストを設定します。

<DataTemplate DataType="{x:Type vm:ChildViewModel}">
    <vw:ChildView/>
</DataTemplate>

最終的な結果として、ビュー モデル オブジェクトを個別に (親クラスと子クラスの両方で) 構築し、コンテンツ コントロールにプラグインするだけで後で表示できます。

于 2009-05-05T16:42:51.383 に答える
5

MVVM アプローチを使用して ViewModel 間で通信する最も簡単な方法は、Mediator パターン (Prism の EventAggregator) を使用することです。このアプローチの良い例は、次のリンクで見ることができます。

  1. Sacha Barber による MVVM メディエーター パターン
  2. MVVM + メディエーター by marlon grech

MVVMサンプルプロジェクト フレームワークも確認してください。

于 2009-05-06T16:04:32.747 に答える
1

QueueViewModelを使用するQueueViewがあるとします。

public class QueueViewModel : INotifyPropertyChanged
{
    public ParentType Parent { get; set; }

    public QueueViewModel(ParentType parent)
    {
        this.Parent = parent;
        foreach (ChildType child in Parent)
        {
            child.PropertyChanged += delegate(object sender,
                PropertyChangedEventArgs e)
            {
                if (e.PropertyName != "IsSelected")
                    return;

                //do something like this:
                Parent.IsSelected = AllChildrenAreSelected();
            };
        }
    }

}

public class ParentType : INotifyPropertyChanged
{
    private bool _isSelected;

    public IList<ChildType> Children { get; set; }
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }
}

public class ChildType : INotifyPropertyChanged
{
    private string _name;
    private bool _isSelected;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }
}

--QueueViewパート

<StackPanel>
<CheckBlock Text="{Binding Path=Parent.Name}" 
            IsChecked="{Binding Parent.IsSelected}"/>
<ItemsControl ItemsSource="{Binding Path=Parent.Children}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>                                    
            <CheckBox Content="{Binding Path=Name}"
                      IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"/>
        </DataTemplate>
    <ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
于 2009-05-05T20:12:39.477 に答える