문제

ViewModels간에 의사 소통하는 방법을 알아 내야합니다. 나는 MVVM을 처음 접 했으니 친절 해요.

다음은 바보 같은 예입니다

클래스 정의 (내가 child.propertychanged 이벤트에서 ParentViewModel을 연결했다고 가정) :

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>

그리고 자식의 코드-홀드 :

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

명백한 문제는 Childview가 (데이터 emplate에서 선택을 통해) 인스턴스화되면 새로운 ChildViewModel 클래스를 생성하고 ParentViewModel에 액세스 할 수 없다는 것입니다.

그렇다면 뷰의 데이터 콘텍스트를 어떻게 DataTemplate을 선택하게 한 원래 뷰 모델이되도록 어떻게해야합니까?

명백한 수정은 ChildViewModel의 특성을 ParentViewModel로 Mmerge하는 것이지만 재사용하기 때문에 오히려 분리하는 것입니다.

나는 대답이 사소한 것이라고 확신합니다. 단지 그것이 무엇인지 알고 싶습니다. :)

미리 감사드립니다.

도움이 되었습니까?

해결책

라인을 간단히 제거해야합니다.

DataContext = new ChildViewModel();

그만큼 DataContext 뷰의는 WPF에 의해 자동으로 설정됩니다. DataTemplates 항상 데이터 컨텍스트가 템플릿의 데이터로 설정되어 있습니다 (이 경우 뷰 모델).

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

최종 결과는 뷰 모델 객체를 별도로 구축 한 다음 (부모 및 자식 수업 모두) 컨텐츠 컨트롤에 연결하여 나중에 표시 할 수 있습니다.

다른 팁

MVVM 접근법을 사용하여 뷰 모델간에 통신하는 가장 쉬운 방법은 중재자 패턴 (프리즘의 Eventaggregator)을 사용하는 것입니다. 이 접근법의 좋은 예는 다음 링크에서 볼 수 있습니다.

  1. Sacha Barber의 MVVM 중재자 패턴
  2. Marlon Grech의 MVVM + 중재자

MVVM도 확인하십시오 견본 프로젝트 프레임 워크.

QueueViewModel을 사용하는 퀘이트 뷰가 있다고 가정 해 봅시다.

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>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top