아마 당신은 백그라운드 작업자가 아닌 UI 스레드에서 프레임 워크 개체를 만들어야한다고 알았습니다. 나는 이것이 질문의 핵심이라고 생각한다.
이것은 어떤 종류의 플러그인 프레임 워크처럼 보입니다. tabContentGenerator
이 삽입되었습니다. 그렇다면 장기 실행 작업과 컨트롤을 만드는 두 가지 작업을 사용합니다. 확장 된 TabControl
은 첫 번째는 DoWork
이고 두 번째는 WorkerCompleted
입니다.
(예를 들어, 의사 코드)
가
public void AddTab(Action backgroundAction, Func<FrameworkElement> constructUiAction)
{
var tab = ...
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => { backgroundAction(); };
worker.RunWorkerCompleted += (sender, e) =>
{
var ui = constructUiAction();
if (ui != null) tab.Content = ui;
};
worker.RunWorkerAsync();
}
다른 옵션이 동작을하는 것이다은 다음 ControlTemplate
통해 UI 스레드에 GUI를 인스턴스화하기 위해 사용하는 FrameworkElementFactory
반환. FrameworkElementFactory
은 DispatcherObject
이 아니며 GUI가 아닌 스레드에서 만들 수 있습니다. 팩토리에서 UI를 만드는 것이 어렵지만 클라이언트가 XAML의 리소스에 컨트롤 템플릿을 지정하면 시각적 트리에서 FrameworkFactoryElement
(예 : ((ControlTemplate)FindResource("MyTemplate")).VisualTree
)을 가져올 수 있습니다.
public void AddTab(Func<FrameworkElementFactory> tabContentGenerator)
{
var tab = ...
var worker = new BackgroundWorker();
FrameworkElementFactory uiFactory = null;
worker.DoWork += (sender, e) => { uiFactory = tabContentGenerator(); }
worker.RunWorkerCompleted += (sender, e) =>
{
if (uiFactory != null)
{
var template = new ControlTemplate();
template.VisualTree = uiFactory;
template.Seal();
tab.Content = template.LoadContent();
};
}
worker.RunWorkerAsync();
}
이것은 실제로 플러그인 프레임 워크이며 우리는 View-First MVVM 패턴을 사용하고 있습니다. 그러나 뷰 생성을 "View creation"과 "ViewModel creation"으로 분리하여 사용자의 코드를 너무 복잡하게 만들고 싶지 않았습니다. ViewModel은 백그라운드 스레드에서 작성되며 ViewModel 준비가 완료되면보기 만 작성됩니다. 뷰를 만들 때 UI 스레드가 사용 중이고 다른 요청을 처리 할 수 없기 때문에 뷰/ViewModel이 생성되는 동안 앱이 응답하기를 원한다면 실제로 선택할 수있는 방법이 없습니다. 저를 깨끗하게 해주셔서 감사합니다. – splintor