2016-07-07 6 views
1

В стартовом экране моей программы я показываю миниатюры (неинтерактивный) UserControl DocumentView для отображения разных документов внутри пользовательского элемента UserControl LoadTileView, пользователь может щелкнуть, чтобы загрузить документ в основной вид. Этот DocumentView также используется в основном представлении для графического представления и редактирования выбранного документа. Поскольку этот DocumentView является графически тяжелым, требуется некоторое время для загрузки, что вызывает огромное время запуска, так как я показываю несколько экземпляров DocumentView внутри стартового экрана (например, различные Плитки, из которых пользователь может выбрать, какой документ редактировать).Передача UIElement в ViewModel с использованием RelayCommand из MVVM-Light

поэтому я работаю на пути, чтобы сохранить кэшированные образ DocumentView экземпляра, который принадлежит каждому LoadingTileView, так что он может быть показан вместо фактического DocumentView, когда моя программа запускается в следующий раз.

В настоящее время я работаю над тем, как сохранять изображения кеша. Моя идея состоит в том, чтобы каждый LoadTileView вызывал свой LoadingTileViewModel через MVVM-Light RelayCommand после его загрузки и передает его команду DocumentView. Я помещаю DocumentView внутри DataTemplate, чтобы я мог заменить его своим кэшированным изображением (и соответствующим представлением), как только он существует, установив CurrentDocumentViewModel соответственно в LoadingTileView.

я нашел объяснение о том, как передать UIElement к ViewModel (here) и как использовать RelayCommand с аргументом (here). В сочетании с триггерами взаимодействия блендера для запуска ViewLoadedEventHandlerCommand в ViewModel появился приведенный ниже код.

Этот код компилируется и запускается, но parameter в ExecuteViewLoadedEventHandlerCommand(object parameter) is Null. Я также пробовал использовать DocumentView напрямую, а не ContentControl, но parameter по-прежнему Null.

Я не уверен, что я делаю неправильно здесь, так как я использовал RelayCommand и Interaction.Triggers это в других случаях, где они работали правильно. Может, кто-нибудь может заметить мою ошибку?

Код для LoadingTileView:

<UserControl.Resources> 
    <DataTemplate DataType="{x:Type ViewModels:DocumentViewModel}"> 
     <View:DocumentView/> 
    </DataTemplate> 
</UserControl.Resources> 

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="Loaded"> 
     <i:InvokeCommandAction Command="{Binding ViewLoadedEventHandlerCommand}" 
           CommandParameter="{Binding ElementName=DocumentViewInstance}"/> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

<Controls:Tile Command="{Binding LoadProgramCommand}"> 
    <Viewbox> 
     <ContentControl x:Name="DocumentViewInstance" Content="{Binding CurrentDocumentViewModel}"/> 
    </Viewbox> 
</Controls:Tile> 

Код для LoadingTileViewModel:

public LoadingTileViewModel() 
{ 
    ... 
    ViewLoadedEventHandlerCommand = new RelayCommand<object>((obj)=>ExecuteViewLoadedEventHandlerCommand(obj)); 
    ... 
} 

public RelayCommand<object> ViewLoadedEventHandlerCommand { get; set; } 
private void ExecuteViewLoadedEventHandlerCommand(object parameter) // object is NULL 
{ 
    UIElement toSave = (UIElement)parameter; 
    //OnViewLoaded(); 
} 

Update:

StackTrace, при разрыве в линии UIElement toSave = (UIElement)parameter;:

Software.UI.ViewModel.dll!ProgramEditor.ViewModel.LoadingTileViewModel.ExecuteViewLoadedEventHandlerCommand(object parameter) Line 168 C# 
Software.UI.ViewModel.dll!ProgramEditor.ViewModel.LoadingTileViewModel.get_ViewLoadedEventHandlerCommand.AnonymousMethod__50_0(object i) Line 184 C# 
[Native to Managed Transition] 
[Managed to Native Transition] 
GalaSoft.MvvmLight.dll!GalaSoft.MvvmLight.Helpers.WeakAction<System.__Canon>.Execute(System.__Canon parameter) Unknown 
GalaSoft.MvvmLight.dll!GalaSoft.MvvmLight.Command.RelayCommand<object>.Execute(object parameter) Unknown 
System.Windows.Interactivity.dll!System.Windows.Interactivity.InvokeCommandAction.Invoke(object parameter) Unknown 
System.Windows.Interactivity.dll!System.Windows.Interactivity.TriggerBase.InvokeActions(object parameter) Unknown 
System.Windows.Interactivity.dll!System.Windows.Interactivity.EventTriggerBase.OnEvent(System.EventArgs eventArgs) Unknown 
System.Windows.Interactivity.dll!System.Windows.Interactivity.EventTriggerBase.OnEventImpl(object sender, System.EventArgs eventArgs) Unknown 
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown 
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown 
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown 
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) Unknown 
PresentationFramework.dll!System.Windows.BroadcastEventHelper.BroadcastEvent(System.Windows.DependencyObject root, System.Windows.RoutedEvent routedEvent) Unknown 
PresentationFramework.dll!System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(object root) Unknown 
PresentationCore.dll!MS.Internal.LoadedOrUnloadedOperation.DoWork() Unknown 
PresentationCore.dll!System.Windows.Media.MediaContext.FireLoadedPendingCallbacks() Unknown 
PresentationCore.dll!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() Unknown 
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object resizedCompositionTarget) Unknown 
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandler(object resizedCompositionTarget) Unknown 
PresentationCore.dll!System.Windows.Media.MediaContext.Resize(System.Windows.Media.ICompositionTarget resizedCompositionTarget) Unknown 
PresentationCore.dll!System.Windows.Interop.HwndTarget.OnResize() Unknown 
PresentationCore.dll!System.Windows.Interop.HwndTarget.HandleMessage(MS.Internal.Interop.WindowMessage msg, System.IntPtr wparam, System.IntPtr lparam) Unknown 
PresentationCore.dll!System.Windows.Interop.HwndSource.HwndTargetFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown 
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown 
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown 
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown 
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown 
[Native to Managed Transition] 
user32.dll!74d862fa() Unknown 
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]  
user32.dll!74d86d3a() Unknown 
user32.dll!74d86ded() Unknown 
user32.dll!74d86e4c() Unknown 
ntdll.dll!773a011a() Unknown 
user32.dll!74d872c1() Unknown 
user32.dll!74dad4ff() Unknown 
user32.dll!74d862fa() Unknown 
user32.dll!74d86d3a() Unknown 
user32.dll!74d90d37() Unknown 
user32.dll!74d90d5d() Unknown 
WindowsBase.ni.dll!6b4a6e70() Unknown 
[Managed to Native Transition] 
WindowsBase.dll!MS.Win32.HwndSubclass.DefWndProcWrapper(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown 
[Native to Managed Transition] 
user32.dll!74d862fa() Unknown 
user32.dll!74d86d3a() Unknown 
user32.dll!74d90d37() Unknown 
user32.dll!74d90d5d() Unknown 
WindowsBase.ni.dll!6b4ced1a() Unknown 
[Managed to Native Transition] 
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown 
[Native to Managed Transition] 
user32.dll!74d862fa() Unknown 
user32.dll!74d86d3a() Unknown 
user32.dll!74d86ded() Unknown 
user32.dll!74d86ded() Unknown 
user32.dll!74d88fb7() Unknown 
ntdll.dll!773a011a() Unknown 
user32.dll!74d92832() Unknown 
user32.dll!74d92802() Unknown 
user32.dll!74d9289a() Unknown 
[Managed to Native Transition] 
MahApps.Metro.dll!Standard.NativeMethods.SetWindowRgn(System.IntPtr hWnd, System.IntPtr hRgn, bool bRedraw) Unknown 
MahApps.Metro.dll!Microsoft.Windows.Shell.WindowChromeWorker._SetRoundingRegion(Standard.WINDOWPOS? wp) Unknown 
MahApps.Metro.dll!Microsoft.Windows.Shell.WindowChromeWorker._UpdateFrameState(bool force) Unknown 
MahApps.Metro.dll!Microsoft.Windows.Shell.WindowChromeWorker._ApplyNewCustomChrome() Unknown 
MahApps.Metro.dll!Microsoft.Windows.Shell.WindowChromeWorker._WindowSourceInitialized(object sender, System.EventArgs e) Unknown 
PresentationFramework.dll!System.Windows.Window.OnSourceInitialized(System.EventArgs e) Unknown 
PresentationFramework.dll!System.Windows.Window.CreateSourceWindow(bool duringShow) Unknown 
PresentationFramework.dll!System.Windows.Window.CreateSourceWindowDuringShow() Unknown 
PresentationFramework.dll!System.Windows.Window.SafeCreateWindowDuringShow() Unknown 
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown 
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() Unknown 
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state) Unknown 
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(object obj) Unknown 
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown 
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown 
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() Unknown 
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() Unknown 
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown 
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown 
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown 
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown 
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown 
[Native to Managed Transition] 
user32.dll!74d862fa() Unknown 
user32.dll!74d86d3a() Unknown 
user32.dll!74d877d3() Unknown 
user32.dll!74d8789a() Unknown 
WindowsBase.ni.dll!6b4ceff4() Unknown 
[Managed to Native Transition] 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Unknown 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Unknown 
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Unknown 
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Unknown 
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Unknown 
PresentationFramework.dll!System.Windows.Application.Run() Unknown 
ProgramEditor.exe!ProgramEditor.App.Main() C# 
[Native to Managed Transition] 
mscoreei.dll!7143cc0b() Unknown 
mscoree.dll!714b7f16() Unknown 
mscoree.dll!714b4de3() Unknown 
kernel32.dll!76d6338a() Unknown 
ntdll.dll!773c9902() Unknown 
ntdll.dll!773c98d5() Unknown 
+0

Если вы устанавливаете DataContext LoadingTileView в конструкторе, то убедитесь, что вы делаете это * до * вызов InitializeComponent() , –

+0

Я бы сказал, что если привязка к команде работает DataContext, значит, это не так. Я действительно думаю, что код выглядит нормально ... Как выглядит stacktrace, когда вы нажимаете 'ExecuteViewLoadedEventHandlerCommand', может быть, вы найдете подсказку о том, где это происходит неправильно ... –

+0

@ MarkusHütter Спасибо за комментарий. К сожалению, стоп-колл не дает мне много просветления. Смотри ниже. Возможно, у вас есть другое предложение? 'LoadingTileViewModel.ExecuteViewLoadedEventHandlerCommand (параметр объекта) LoadingTileViewModel..ctor.AnonymousMethod__24_0 (объект OBJ) [Внешний код] [Фреймы ниже могут быть неправильными и/или отсутствует, никакие символы, загруженные для user32.dll]' – packoman

ответ

0

Оказывается, что проблема была, что Loaded событие TileViewвыпустили до тогоDocumentView внутри DataTemplate загружен. Я нашел это, присоединив другую команду в моем DocumentViewModel к событию LoadedDocumentView. Впоследствии я увидел ответ Маркуса, и это по существу то, что он предложил.

В конце концов, я получил свой код, переместив команду для события Loaded в DataTemplate. Для этого я использовал StackPanel, чтобы связать его Loaded события, так что я закончил с:

<DataTemplate DataType="{x:Type ViewModels:DocumentViewModel}"> 
    <StackPanel> 
     <View:DocumentView x:Name="DocumentViewInstance"/> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="Loaded"> 
       <i:InvokeCommandAction Command="{Binding Path=DataContext.ViewLoadedEventHandlerCommand, 
                 RelativeSource={RelativeSource FindAncestor, 
                         AncestorType={x:Type UserControl}}}" 
             CommandParameter="{Binding ElementName=DocumentViewInstance}"/> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </StackPanel> 
</DataTemplate> 
0

в комментариях, которые вы говорите, что someinput достигает этой команды. Это означает, что привязка имени элемента либо полностью или поздно не работает.

Итак: для тестирования добавьте Button, который имеет то же самое i:InvokeCommandAction, но на <i:EventTrigger EventName="Click"> таким образом вы можете проверить, будет ли более поздняя привязка работать.

Также следите за Выход Окно в VS во время отладки. Если сбой связи невозможен, должно быть сообщение.

Мое предположение заключается в том, что проблема в вашем управлении Tile. Я бы предположил, что ваш элемент управления Tile еще не инициализировал свои дочерние элементы, когда происходит событие Loaded.

+0

Да, в конце концов, это было так. Как описано в моем ответе, DataTemplate инициализируется после элемента 'Tile'. Интересно, является ли это поведение по умолчанию для 'ContentControl'? – packoman

Смежные вопросы