2014-11-19 10 views
3

IPage 인터페이스 (내가 만든 인터페이스)를 구현하는 ViewModel에는 4 개의 클래스가 있습니다. 내 응용 프로그램의 ViewModel에서 IPage 형식의 CurrentPage 속성을 사용했습니다.내 경우 WPF가 올바른 DataTemplate을 선택하지 않는 이유는 무엇입니까?

내 앱의보기 레이어에서 Content가 CurrentPage 속성에 바인딩 된 ContentControl을 사용했습니다. 나는 오른쪽 DataTemplate을

<UserControl ...> 
    <ContentControl Content="{Binding CurrentPage, Mode=OneWay}" 
        VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> 
     <ContentControl.Resources> 
      <DataTemplate DataType="{x:Type operation:OperationListPageVM}"> 
       <pages1:OperationListPageV/> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type operation:OperationDetailPageVM}"> 
       <pages1:OperationDetailPageV/> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type part:PartListPageVM}"> 
       <pages1:PartListPageV/> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type part:PartDetailPageVM}"> 
       <pages1:PartDetailPageV/> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type pages:SettingsPageVM}"> 
       <pages1:SettingsPageV/> 
      </DataTemplate> 
     </ContentControl.Resources> 
    </ContentControl> 
</UserControl> 

를 찾을 수 없습니다 다음 코드 WPF를 사용하지만있을 때 나는 단지 ContentControl.ContentTemplate로 한 DataTemplate을 넣으면

그래서, 그것은

올바르게 적용 할 수 있습니다 그때 자원으로 다시 그 DataTemplates을 넣으면
<UserControl ...> 
    <ContentControl Content="{Binding CurrentPage, Mode=OneWay}" 
        VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> 
     <ContentControl.ContentTemplate> 
      <DataTemplate DataType="{x:Type operation:OperationListPageVM}"> 
       <pages1:OperationListPageV/> 
      </DataTemplate> 
     </ContentControl.ContentTemplate> 
    </ContentControl> 
</UserControl> 

는 그들에게 키를 제공하고 DataTemplateSelector를 생성하고 추가

ContentTemplateSelector="{StaticResource PageTemplateSelector}" 
이 같은 DataTemplateSelector와의 ControlTemplate으로 16,

:

using System.Windows; 
using System.Windows.Controls; 
using MaintenanceModuleV3.ViewModel; 
using MaintenanceModuleV3.ViewModel.Pages; 
using MaintenanceModuleV3.ViewModel.Pages.Operation; 
using MaintenanceModuleV3.ViewModel.Pages.Part; 

namespace MaintenanceModuleV3.View.TemplateSelector { 
    public class PageTemplateSelector : DataTemplateSelector { 
     public override DataTemplate SelectTemplate(object item, DependencyObject container) { 
      if (AppVM.Instance.CurrentPage != null) { 
       if (AppVM.Instance.CurrentPage is OperationListPageVM) { 
        return (container as FrameworkElement).FindResource("OperationListPageTemplate") as DataTemplate; 
       } else if (AppVM.Instance.CurrentPage is OperationDetailPageVM) { 
        return (container as FrameworkElement).FindResource("OperationDetailPageTemplate") as DataTemplate; 
       } else if (AppVM.Instance.CurrentPage is PartListPageVM) { 
        return (container as FrameworkElement).FindResource("PartListPageTemplate") as DataTemplate; 
       } else if (AppVM.Instance.CurrentPage is PartDetailPageVM) { 
        return (container as FrameworkElement).FindResource("PartDetailPageTemplate") as DataTemplate; 
       } else if (AppVM.Instance.CurrentPage is SettingsPageVM) { 
        return (container as FrameworkElement).FindResource("SettingsPageTemplate") as DataTemplate; 
       } 
      } 
      return null; 
     } 
    } 
} 

은 다음 오른쪽 DataTemplate을이 선택이 끝난됩니다.

DataTemplates를이 경우 요소 리소스에 넣으면 WPF가 올바른 DataTemplate을 선택하지 않는 이유는 무엇입니까?

편집을 프레임 워크 3.5을 사용하여 :

당신에게

NB 감사합니다 DataTemplates가 null의 내부의 DataContext : 나는 두 번째 문제를 발견. 왜 그런가요? 왜 CurrentPage를 DataContext로 사용하지 않습니까? ContentTemplate을 직접 설정할 때도 마찬가지입니다. WPF는 바인딩을 인터페이스 형식화 된 속성에 싫어하는 것 같습니다.

EDIT 2 : OperationListPageV의 DataContext를 해당 생성자에서 명시 적으로 설정하고 TemplateSelector를 사용하면 모든 것이 작동하지만 왜 그 데이터를 사용해야합니까?

편집 3 : 전체 뷰 모델 코드, 도움이된다면 :

응용 뷰 모델

public class AppVM : INotifyPropertyChanged { 

    #region constructor 
    private AppVM() { 
     AppM.LanguageChanged += (sender, args) => { 
      onPropertyChanged("CurrentLanguage"); 
     }; 

     AppM.NbDaysAvgChanged += (sender, args) => { 
      onPropertyChanged("NbDaysAvg"); 
     }; 

     AppM.NbDaysMenuNotificationChanged += (sender, args) => { 
      onPropertyChanged("NbDaysMenuNotification"); 
     }; 
    } 
    #endregion 

    #region business 

    #endregion 

    #region events 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void onPropertyChanged(string propertyName) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    #endregion 

    #region properties 

    private static AppVM _instance; 
    public static AppVM Instance { 
     get { return _instance ?? (_instance = new AppVM()); } 
    } 


    #region notifypropertychanged 
    private OperationListPageVM _currentPage = OperationListPageVM.Instance; 
    public OperationListPageVM CurrentPage { 
     get { return _currentPage; } 
     set { 
      _currentPage = value; 
      onPropertyChanged("CurrentPage"); 
     } 
    } 

    public Language CurrentLanguage { 
     get { return AppM.CurrentLanguage; } 
    } 

    public int NbDaysMenuNotification { 
     get { return AppM.NbDaysMenuNotification; } 
    } 

    public int NbDaysAvg { 
     get { return AppM.NbDaysAvg; } 
    } 

    public Dictionary<String, String> AvailableTranslations { 
     get { return AppM.AvailableTranslations; } 
    } 
    #endregion 
    #region commands 
    #endregion 
    #endregion 
} 

내가 ViewModel에

public sealed class OperationListPageVM : INotifyPropertyChanged, IPage { 

    #region constructor 
    private OperationListPageVM() { 
     //fill the available operations with data stored in the App Model coming from the DataBase 
     foreach (MaintenanceOperation operation in AppM.Operations) { 
      AvailableOperations.Add(new MaintenanceOperationVM(operation)); 
     } 
     foreach (MaintenanceOperationVM operation in AvailableOperations) { 
      DisplayedOperations.Add(operation); 
     } 
    } 
    #endregion 

    #region business 

    #endregion 

    #region events 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void onPropertyChanged(string propertyName) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    #endregion 

    #region properties 

    private static OperationListPageVM _instance; 

    public static OperationListPageVM Instance { 
     get { return _instance ?? (_instance = new OperationListPageVM()); } 
    } 

    #region notifypropertychanged 
    private ObservableCollection<MaintenanceOperationVM> _displayedOperations = new ObservableCollection<MaintenanceOperationVM>(); 
    public ObservableCollection<MaintenanceOperationVM> DisplayedOperations { 
     get { return _displayedOperations; } 
     set { 
      _displayedOperations = value; 
      onPropertyChanged("DisplayedOperations"); 
     } 
    } 

    private readonly List<MaintenanceOperationVM> _availableOperations = new List<MaintenanceOperationVM>(); 

    internal List<MaintenanceOperationVM> AvailableOperations { 
     get { return _availableOperations; } 
    } 

    #endregion 

    #region commands 

    #endregion 

    #endregion 
} 

를 표시하는 것이었다 페이지 표시 할 페이지의 계층보기 (OperationListPageV)

<UserControl x:Class="MaintenanceModuleV3.View.Pages.OperationListPageV" 
      ...> 
    <touch:ScrollFriction2> 
     <ListBox ItemsSource="{Binding DisplayedOperations}"> 
       <ListBox.ItemContainerStyle> 
        <Style TargetType="{x:Type ListBoxItem}"> 
         <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 
        </Style> 
       </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate DataType="{x:Type viewModel:MaintenanceOperationVM}"> 
        <view:MaintenanceOperationV/> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </touch:ScrollFriction2> 
</UserControl> 

더 많은 코드가 필요한 경우 요청하십시오. 고맙습니다!

+0

댓글은 확장 토론이 아닙니다. 이 대화는 [채팅으로 이동되었습니다] (http://chat.stackoverflow.com/rooms/65201/discussion-on-question-by-nkoniishvt-why-wont-wpf-choose-the-right-datatemplate). – Flexo

답변

0

ItemControl의 Resources에 템플릿을 넣으십시오. 나는 그들이 왜 이런 식으로 만들 었는지 모르지만 ContentControl보다 한 레벨 위에 있어야합니다.