Witajcie !
Mam flagę IsCurrentlyLogged (ustawioną ze startu na false) oraz 2 x <grid>.
Początkowo grid1 jest widoczny, a grid2 nie.
Gdy IsCurrentlyLogged zmieni się na TRUE chciałbym, aby grid1 zniknął natychmiast (zwykły trigger), a grid2 pojawił się płynnie.
Myślałem, żeby zrobić to drugie za pomocą EventTriggera i animacji, jednak nie potrafię dobrać odpowiedniego RoutedEventu. Wtedy sztucznie w setterze ustawiałbym focusa czy coś, ale to mało profesjonalne. Macie jakieś sugestie? I dlaczego w zwykłym triggerze nie można robić animacji?
Żeby zrobić animację znikania i pojawiania się kontrolki możesz zrobić taki mały myk. Ze zwykłym Visibility
się nie da.
XAML:
<Window x:Class="WPF_4Prog.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_4Prog"
mc:Ignorable="d"
Title="MainWindow"
WindowStartupLocation="CenterScreen" SizeToContent="Height"
Width="400" ResizeMode="NoResize">
<Grid Height="{Binding InnerGridHeight, UpdateSourceTrigger=PropertyChanged}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Grid.Column="0">
<Button Content="Up" Command="{Binding UpPressed}" Height="30"
VerticalAlignment="Top" DockPanel.Dock="Top"/>
<Button Content="Down" Command="{Binding DownPressed}"
VerticalAlignment="Bottom" DockPanel.Dock="Top"
Height="{Binding LowerButtonHeight, UpdateSourceTrigger=PropertyChanged}"/>
</DockPanel>
</Grid>
</Window>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows;
using System.Timers;
using WPF_4Prog.Commands;
using WPF_4Prog.Helpers;
using WPF_4Prog.Interfaces;
namespace WPF_4Prog.ViewModel
{
public class MainWindowVM : ViewModelBase
{
private enum Action
{
Folding,
Expanding
}
private int innerGridHeight;
public int InnerGridHeight
{
get { return this.innerGridHeight; }
set
{
this.innerGridHeight = value;
this.OnPropertyChanged(nameof(this.InnerGridHeight));
}
}
private int lowerButtonHeight;
public int LowerButtonHeight
{
get { return this.lowerButtonHeight; }
set
{
this.lowerButtonHeight = value;
this.OnPropertyChanged(nameof(this.LowerButtonHeight));
}
}
public MainWindowVM()
{
this.InnerGridHeight = 200;
this.LowerButtonHeight = 0;
}
public ICommand UpPressed
{
get
{
return new RelayCommand(() =>
{
this.ProcessLowerButton(Action.Expanding);
});
}
}
public ICommand DownPressed
{
get
{
return new RelayCommand(() =>
{
this.ProcessLowerButton(Action.Folding);
});
}
}
private void ProcessLowerButton(Action action)
{
var upperButtonHeight = 30;
var timer = new Timer(5);
timer.Elapsed += (sender, e) =>
{
switch (action)
{
case Action.Folding:
{
if (this.LowerButtonHeight > 0) this.LowerButtonHeight--;
else timer.Stop();
break;
}
case Action.Expanding:
{
if (this.LowerButtonHeight < this.InnerGridHeight - upperButtonHeight) this.LowerButtonHeight++;
else timer.Stop();
break;
}
}
};
timer.Start();
}
}
}
ViewModelBase:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace WPF_4Prog.Helpers
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I kontrolka ładnie się rozwija. Trzeba by tylko pilnować żeby się nie odpalał więcej niż jeden timer
i takie tam inne rzeczy, bo to przykład pisany na szybko.
Ale działa.
Faktycznie tak to można zrobić. Ale czytam o animacjach i chcę w zależności od triggera zmieniać opacity usercontrola. Jednak animacje mogę ustawiać tylko w eventtriggerze, trigger zwykły tego nie obsługuje. Da się to jakoś obejść? Chodzi tu o sam WPF, to musi być możliwe do zrobienia :)
@grzesiek51114 wiem jak zrobić to w c#, ale mi chodzi jak to zrobić w WPF. Chodzi mi o wykorzystanie do tego animacji. Np. nie mam problemu z płynną zmianą rozmiaru tekstu "Zarejestruj się", ale nie wiem jak Wywołać animację w momencie zmiany zmiennej typu bool.
Triggery jak najbardziej obsługują animacje ;)
<Grid Margin="0,85,0,0">
<Grid.Resources>
<Style TargetType="Grid">
<Setter Property="Background" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsCurrentlyLogged}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.0" To="1.0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
</Grid>