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>
더 많은 코드가 필요한 경우 요청하십시오. 고맙습니다!
댓글은 확장 토론이 아닙니다. 이 대화는 [채팅으로 이동되었습니다] (http://chat.stackoverflow.com/rooms/65201/discussion-on-question-by-nkoniishvt-why-wont-wpf-choose-the-right-datatemplate). – Flexo