2010-02-10 4 views
3

내 앱에 MVVM 패턴을 사용하고 있습니다. MainWindow를은 뷰 모델에 매핑 된 DataContextTabControl을 포함한다 :TabControl은 비활성 탭에 컨트롤을 삭제합니다.

<Window.Resources> 
    <ResourceDictionary> 
    <DataTemplate x:Key="templateMainTabControl"> 
     <ContentPresenter Content="{Binding Path=DisplayName}" /> 
    </DataTemplate> 

    <local:ViewModel x:Key="VM" /> 
    <local:WorkspaceSelector x:Key="WorkspaceSelector" /> 
    <local:TabOneView x:Key="TabOneView" /> 
    <local:TabTableView x:Key="TabTableView" /> 

    <DataTemplate x:Key="TabOne"> 
     <local:TabOneView /> 
    </DataTemplate> 

    <DataTemplate x:Key="TabTable"> 
     <local:TabTableView /> 
    </DataTemplate> 

    </ResourceDictionary> 
</Window.Resources> 


<TabControl Grid.Row="0" 
      DataContext="{StaticResource VM}" 
      ItemsSource="{Binding Workspaces}" 
      SelectedItem="{Binding SelectedWorkspace}" 
      ItemTemplate="{StaticResource templateMainTabControl}" 
      ContentTemplateSelector="{StaticResource WorkspaceSelector}" /> 

WorkspaceSelector은 다음과 같습니다

public class WorkspaceSelector : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
    Window win = Application.Current.MainWindow; 
    Workspace w = (Workspace) item; 
    string key = w.DisplayName.Replace(" ", ""); 
    if (key != "TabOne") 
    { 
     key = "TabTable"; 
    } 
    return win.FindResource(key) as DataTemplate; 
    } 
} 

그래서 TabOneDataTemplate를 반환합니다. TabOne이고 다른 두 개의 탭은 DataTemplateTabTable을 반환합니다. 나는 응용 프로그램을 실행하고 두 번 각 탭을 클릭하면

(1, 2, 3, 1, 2, 3) 나는 이


TABONE의 뷰가 만들어

인 기대하지 않습니다
TabTwo의보기는
TABONE의보기가 TemplateSelector가 다른 값을 반환하는 경우, 기존의 탭의 컨트롤 멀리 던져되고의 새 탭의 컨트롤이 만들어

을 만들어
TabTwo의 뷰를 생성 생성, 그리고 만약됩니다 TemplateSelector 후퇴 ns가 같은 값이면 아무 일도 일어나지 않습니다.

이것은 내가 원하지 않는 것입니다. TabControl에서 탭의 모든 컨트롤을 유지하고 싶습니다. TabTwo에서 TabThree으로 이동하는 경우 코드의 다른 컨트롤을 만드는 방법에 대해 뭔가 할 수 있기를 바랍니다. 나는 후자없이 살 수있다. 그러나 각 탭의 컨트롤이 선택되지 않은 경우 버리지 않도록 TabControl에 어떻게 말합니까?

답변

4

이것은 TabControl의 기능이며 기본 동작입니다.

기본적으로 메모리를 절약하기 위해 TabControl은 내용 영역에있는 시각적 트리를 언로드하고 새 탭에 대해 새로 뭉치는 것으로 대체합니다. 이 사실을 증명하기 위해 템플릿을 입력 할 때마다 Unload 이벤트를 수신 할 수 있으며 탭을 전환 할 때마다 해당 이벤트가 발생합니다. 당신은 상당한 성능 저하가있을 것이라고 생각

  1. :

    는이 동작을 재정의 할 것 2 가지 이유로 가능성이 있습니다.

  2. 손실되는 시각적 상태가 ViewModel에 의해 뒷받침되지 않으므로 컨트롤의 상태가 손실됩니다.

# 1에 대해서는 걱정할 필요가 없습니다. CPU 시간은 일반적으로 RAM보다 저렴하며 기본 동작은 리소스 방정식의 저렴한쪽에 기댄다. 여전히이 동작을 원하지 않는다면 다음과 같이 무시하십시오. https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/Controls/NonReloadingTabControl.cs

그러나 나는 미래의 성능 문제를 해결하기 위해 "냄새"라고 생각할 것입니다. 이제는 알아내는 것을 지연하기보다는 시간을 알아 내야합니다.

  1. 상태 것을 보존하는 뷰 모델에 의해 당신이 보존하려는 모든 재산 (같은 IsSelected 등)가 백업되어 있는지 확인하십시오 :

    # 2를 들어, 두 가지 옵션이 있습니다.

  2. ViewModels (사용자의 경우 Workspaces)가 아니라 바인딩 할 각 탭에 대해 영구적 인 UserControl을 만듭니다. WAF의 "Writer"샘플에 그 예가 있습니다. http://waf.codeplex.com/
+0

감사합니다. Anderson - 이유가 1 (비싸다고 느껴짐)였습니다. 나는 그 흐름을 따라 갈거야. --Amaca – amaca

+0

# 1을 해결해야합니다. 각 탭 변경시 설정하는 데 비용이 많이 드는 DataGrid가 있습니다. tabcontrol에게 탭의 내용을 개별적으로 유지하면서 언로드하지 않도록 어떻게 말할 수 있습니까? – DarkwingDuck

+0

@DarkwingDuck : Telerik이 해킹을 발견했습니다. 메모리 사용량에 대해서는 전혀 모른다. YMMV. http://www.pluralsight-training.net/community/blogs/eburke/archive/2009/04/30/keeping-the-wpf-tab-control-from-destroying-its-children.aspx보고 싶습니다. 탁월한 WPF 성능 도구 중 하나인데, 퍼포먼스가 생각되면 어디에서 빠져 나오는지 확인할 수 있습니다. 그 링크는 다음과 같습니다. http://msdn.microsoft.com/en-us/library/aa969767.aspx –