2014-04-21 4 views
2

을 사용하는보기 탐색에 대한 조언 Caliburn Micro에서 새로 도입되었으며 내 앱 인터페이스 및보기 간 탐색을 위해 devolop을 사용할 경로에 대한 조언을 원합니다. 제 아이디어는 각각의 특정보기와 관련된 단추 메뉴를 포함하는 MainWindow를 갖는 것입니다. 각보기는 분리 된 WPF UserControl에 저장됩니다. mainWindow에는 viewmodel의 ObservableCollection 탭에 바인드 된 TabControl도 포함됩니다. 메뉴의 버튼을 클릭 할 때마다 뷰와 해당 뷰 모델을 동적으로로드하는 ContentPresenter가있는 새 탭을 추가하려고합니다.Caliburn.Micro MVVM WPF

그래서 내 질문은 :

1) 나는 여기에 화면 컬렉션을 사용해야합니까?

2) UserControl이 Screen 인터페이스를 구현해야합니까?

3) MainWindow ViewModel에서 분리 된 뷰 모델을 유지 관리하는 새로운 추가 탭에서로드 할 뷰를 어떻게 말합니까?

미리 감사드립니다.

UPDATE 독서를 많이하고 지역 사회의 도움 후 나는이 문제를 해결 할 수 있었다. 이 결과 AppViewModel입니다 :

class AppViewModel : Conductor<IScreen>.Collection.OneActive 
{ 
    public void OpenTab(Type TipoVista) 
    { 
     bool bFound = false; 
     Screen myScreen = (Screen)Activator.CreateInstance(TipoVista as Type); 
     myScreen.DisplayName = myScreen.ToString(); 
     foreach(Screen miItem in Items) 
     { 
      if (miItem.ToString() == myScreen.ToString()) 
      { 
       bFound = true; 
       ActivateItem(miItem); 
      }     
     } 
     if (!bFound) ActivateItem(myScreen);   
    } 

    public ObservableCollection<MenuItem> myMenu { get; set; } 
    public ObservableCollection<LinksItem> myDirectLinks { get; set; } 

    public ICommand OpenTabCommand 
    { 
     get 
     {     
      return new RelayCommand(param => this.OpenTab((Type) param), null); 
     } 
    }  

    public AppViewModel() 
    { 
     OpenTab(typeof(ClientsViewModel));    
     MenuModel menu = new MenuModel(); 
     myMenu = menu.getMenu(); 
     myDirectLinks = menu.getLinks(); 
    }   

    public void CloseTab(Screen param) 
    {    
     DeactivateItem(param, true); 
    }  
} 

내가 Caliburn.micro의 이름 규칙은 DataTemplate을 내부에서 작동하는 것 같다하지 않기 때문에 OpenTabCommand에서 ICommand의를 유지해야합니다. 다른 사람을 도울 수 있기를 바랍니다. 모두에게 감사합니다

답변

3

나는 매우 비슷한 것을 을 사용하여 작성했으며 예제에 포함 된 SimpleMDI 예제를 기반으로하고 있으며, 필자의 요구에 맞게 몇 가지 조정을했습니다. - 상기 ConductorItems의 속성에 바인딩 <TabControl x:Name="Items">

public class ShellViewModel : Conductor<IScreen>.Collection.OneActive 
{ 
} 

대응 ShellViewTabControl 함유 :

많은 예에서와 같이, I는 ShellViewModel 본체가 있었다.

이 특정 경우에, 나는 또한 인스턴스화 일련의 명령에합니다 (Caliburn.Micro 규칙을 사용) 결합, 내 ShellViewContextMenu했다 Activated 다양한 ViewModels (보통은에 ActivateItem 방법을 사용하여, UserControl 상응하는 이 경우에서 Conductor.

public class YourViewModel: Conductor<IScreen>.Collection.OneActive 
{ 
    // ... 

    public void OpenItemBrowser() 
    { 
     // Create your new ViewModel instance here, or obtain existing instance. 
     // ActivateItem(instance) 
    } 
} 

, 나는 특정 의존성으로 생성 할 ViewModels, 또는 프로그램의 다른 위치에서 필요로하지 않았다.

다른 곳에서 ViewModel을 트리거해야 할 때 Caliburn.MicroEventAggregator을 사용하여 맞춤 이벤트를 게시했습니다. OpenNewBrowser). 해당 인터페이스를 구현하는 클래스에서 처리 할 수 ​​있습니다 (예 :문서의

public class YourViewModel: Conductor<IScreen>.Collection.OneActive, IHandle<OpenNewBrowser> 
{ 
    // ... 

    public void Handle(OpenNewBrowser myEvent) 
    { 
     // Create your new ViewModel instance here, or obtain existing instance. 
     // ActivateItem(instance) 
    } 
} 

This section

아마 도움이 될 것입니다, 특히 간단한 MDI 섹션 : IHandle<OpenNewBrowser>)는, 그래서 당신의 주요 ViewModel 필요한 View을 여는 책임 간단한 Handle 방법을 가질 수 있습니다.

추가 코드 나 코멘트에서 언급 :이 라인은 내가 특정 유형의 화면의 기존 인스턴스가있는 경우, 그것은으로 전환하거나 새 인스턴스를 만들 수 있도록 함께

가끔 일반적인 방법을 사용 그렇지 않다면.

public void OpenBrowser() 
{ 
    this.ActivateOrOpen<BrowserViewModel>(); 
} 
+0

가 대단히 감사합니다 :

public void ActivateOrOpen<T>() where T : Screen { var currentItem = this.Items.FirstOrDefault(x => x.GetType() == typeof(T)); if (currentItem != null) { ActivateItem(currentItem); } else { ActivateItem(Activator.CreateInstance<T>()); } } 

처럼 사용! 이것은 내가 필요한 것입니다! 나는 약간의 테스트를 끝내었고 SimpleMDI를 자신의 필요에 맞게 간단하게 적용 할 수 있음을 발견했다. 내가 한 유일한 차이점은 ActivateItem을 사용하여 새로운 뷰를 여는 방법입니다. 특정 뷰에 모든 메뉴 옵션을 연결하고자하는 메뉴가 있기 때문에 "myScreen = (Screen) Activator.CreateInstance (ViewType as Type); " ViewType을 viewmodel 클래스 유형에 대한 참조로 전달합니다. 내 업데이 트가 표시되면 내 AppViewModel을 게시합니다. 다시 감사합니다! – ericpap

+0

그럴 수 있습니다 = D 때로는 하나의 인스턴스 만 필요로하는 스크린을 제어하기 위해 제네릭 메소드를 사용합니다. 여기에 쐐기를 넣으 려하지 않고 편집에 게시합니다. – Chris