MVVM Navigation Switching ViewModels вызывает ошибку с анимацией - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь создать приложение 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 при переключении на другое и как?

1 Ответ

0 голосов
/ 08 февраля 2020

Я нашел решение, которое работает, но я не уверен относительно , почему это сработало. Я удалил весь XAML, связанный с анимацией, и переместил анимацию в код в HomeView.xaml.

Вот код:

public partial class HomeView : UserControl
{

    private Storyboard _mouseEnterStoryboard;
    private Storyboard _mouseLeaveStoryboard;
    private DoubleAnimation _scaleX_In;
    private DoubleAnimation _scaleY_In;
    private DoubleAnimation _scaleX_Out;
    private DoubleAnimation _scaleY_Out;

    public HomeView()
    {
        InitializeComponent();

        _mouseEnterStoryboard = new Storyboard();

        ScaleTransform scaleVaultsButton = new ScaleTransform(1.0, 1.0);
        ScaleTransform scaleFilesButton = new ScaleTransform(1.0, 1.0);

        VaultsButton.RenderTransformOrigin = new Point(0.5, 0.5);
        VaultsButton.RenderTransform = scaleVaultsButton;

        FilesButton.RenderTransformOrigin = new Point(0.5, 0.5);
        FilesButton.RenderTransform = scaleFilesButton;

        _scaleX_In = new DoubleAnimation()
        {
            Duration = TimeSpan.FromMilliseconds(100),
            From = 1.0,
            To = 1.08
        };

        _scaleY_In = new DoubleAnimation()
        {
            Duration = TimeSpan.FromMilliseconds(100),
            From = 1.0,
            To = 1.08
        };

        _mouseEnterStoryboard.Children.Add(_scaleX_In);
        _mouseEnterStoryboard.Children.Add(_scaleY_In);

        Storyboard.SetTargetProperty(_scaleX_In, new PropertyPath("RenderTransform.ScaleX"));
        Storyboard.SetTargetProperty(_scaleY_In, new PropertyPath("RenderTransform.ScaleY"));

        _mouseLeaveStoryboard = new Storyboard();

        _scaleX_Out = new DoubleAnimation()
        {
            Duration = TimeSpan.FromMilliseconds(100),
            From = 1.08,
            To = 1.0
        };

        _scaleY_Out = new DoubleAnimation()
        {
            Duration = TimeSpan.FromMilliseconds(100),
            From = 1.08,
            To = 1.0
        };

        _mouseLeaveStoryboard.Children.Add(_scaleX_Out);
        _mouseLeaveStoryboard.Children.Add(_scaleY_Out);

        Storyboard.SetTargetProperty(_scaleX_Out, new PropertyPath("RenderTransform.ScaleX"));
        Storyboard.SetTargetProperty(_scaleY_Out, new PropertyPath("RenderTransform.ScaleY"));

        VaultsButton.MouseEnter += new MouseEventHandler(Button_MouseEnter);
        VaultsButton.MouseLeave += new MouseEventHandler(Button_MouseLeave);

        FilesButton.MouseEnter += new MouseEventHandler(Button_MouseEnter);
        FilesButton.MouseLeave += new MouseEventHandler(Button_MouseLeave);

    }

    public void Button_MouseEnter(object sender, MouseEventArgs e)
    {
        Storyboard.SetTarget(_scaleX_In, (Button)sender);
        Storyboard.SetTarget(_scaleY_In, (Button)sender);
        _mouseEnterStoryboard.Begin();
    }

    public void Button_MouseLeave(object sender, MouseEventArgs e)
    {
        Storyboard.SetTarget(_scaleX_Out, (Button)sender);
        Storyboard.SetTarget(_scaleY_Out, (Button)sender);
        _mouseLeaveStoryboard.Begin();
    }

}

Я не уверен, что почему это работает, а версия XAML - нет, поэтому я все еще хотел бы получить ответ на этот вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...