Я пытаюсь создать приложение WPF, используя шаблон MVVM. Теперь я хочу иметь возможность перемещаться между ViewModels, и для этого я использовал эту статью: https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
По сути, ресурсы Главного окна содержат шаблоны данных для каждой модели представления, связывающие его к его представлению и к элементу управления контентом, привязанному к CurrentPageViewModel, например:
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModels:HomeViewModel}">
<Views:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:VaultViewModel}">
<Views:VaultView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:VaultsViewModel}">
<Views:VaultsView />
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentPageViewModel}" />
В конструкторе главного окна я установил CurrentPageViewModel на новый экземпляр моей модели представления домашнего экрана, и когда я хочу перемещаться, все, что мне нужно сделать, это изменить CurrentPageViewModel, а WPF сделает все остальное из-за моего использования INotifyPropertyChanged
.
Я отправляю запросы на изменение страницы в главное окно из моих моделей просмотра, копируя код из мессенджера MVVM Light , реализующего шаблон Mediator, и это прекрасно работает, за исключением случаев, когда у меня воспроизводятся раскадровки.
У меня есть две очень приятные кнопки на моей домашней странице, которые немного растут при наведении курсора поверх них:
<Button Style="{DynamicResource MaterialButton}" Width="400px" Height="400px" Margin="15px"
FontSize="24" FontFamily="Roboto" FontWeight="Bold"
Effect="{DynamicResource HomeButtonDropShadowEffect}" Command="{Binding DisplayVaultsView}"
Content="Vaults">
<!--#region button effects -->
<Button.RenderTransform>
<ScaleTransform x:Name="scaleTransform" CenterX="200" CenterY="200" ScaleX="1.0" ScaleY="1.0"/>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="scaleTransform"
Storyboard.TargetProperty="ScaleX"
To="1.08" Duration="0:0:0.1"/>
<DoubleAnimation
Storyboard.TargetName="scaleTransform"
Storyboard.TargetProperty="ScaleY"
To="1.08" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="scaleTransform"
Storyboard.TargetProperty="ScaleX"
To="1.0" Duration="0:0:0.1" FillBehavior="Stop"/>
<DoubleAnimation
Storyboard.TargetName="scaleTransform"
Storyboard.TargetProperty="ScaleY"
To="1.0" Duration="0:0:0.1" FillBehavior="Stop"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
<!--#endregion-->
</Button>
Как видите, команда кнопки установлена на DisplayVaultsView, который является метод внутри HomeViewModel, который отправляет запрос на изменение страницы в главное окно. Без этих раскадровок внутри кнопки это работает просто отлично, и отображается новая страница. Однако в раскадровках после нажатия кнопки выдается следующая ошибка: System.InvalidOperationException: ''scaleTransform' name cannot be found in the name scope of 'System.Windows.Controls.Button'.'
Это привело меня к мысли, что анимация все еще пытается воспроизвести, но поскольку кнопка не находится в текущем контекст больше не может найти свойство, которое он должен анимировать.
Также важно отметить, что HomeViewModel не выбрасывается при переходе на другую страницу, я написал свой собственный класс Navigator, который отслеживает ViewModels, чтобы вы могли перемещаться вперед / назад без потери изменений. (и без необходимости перезагружать все).
Я хотел бы знать, как я могу решить эту ошибку, но это также привело меня к осознанию того, что мне может потребоваться «выгрузить» ViewModels при переключении на другое один. В настоящее время я просто храню все ссылки ViewModel внутри List внутри класса Navigator. Таким образом, мой другой вопрос, должен ли я «разгрузить» ViewModels при переключении на другое и как?