Jump to content
Mlourenco

Sliding Panel para paginacao de elementos com animação

Recommended Posts

Mlourenco

Boas, ando a investigar WPF, e comecei a fazer umas bricadeiras. Algo que estou a tentar criar é um controlo para fazer paginacao entre elementos numa window com uma animacao entre as paginas.

Para tal crio uma grid dentro de um canvas e vou alterando o Canvas.Left da Grid para me mostrar a pagina que quero.

O problema com que me deparei é que tenho que definir um tamanho fixo para cada pagina, quando queria que cada pagina ocupasse a totalidade da janela.

Partilho aqui o projecto, e gostava de saber se alguem tem alguma sugestao para resolver o meu problema, queria ter o User Control o mais dinamico possivel sem ter de definir tamanhos fixos...

DynamicSlidePanel.xaml

<UserControl x:Class="WpfSlidePanel.DynamicSlidePanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Name="rootGrid" >
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions>
        <Canvas Name="canvasMain" Margin="0" Width="Auto" ClipToBounds="True">
            <Grid Canvas.Left="0" Name="mainGrid">

            </Grid>
        </Canvas>


        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Name="spPaging">
            <Button Content="<"  Height="23"  Name="btnPreviousPage" VerticalAlignment="Center" Width="30" Click="btnPreviousPage_Click" />
            <TextBlock Height="17" Margin="10 3 10 3" HorizontalAlignment="Left"  Name="tbPageNumber" Text="Page 0 / 0" VerticalAlignment="Center" />
            <Button Content=">" Height="23" Name="btnNextPage" VerticalAlignment="Center" Width="30" Click="btnNextPage_Click" />
        </StackPanel>
    </Grid>
</UserControl>

DynamicSlidePanel.xaml.cs

public partial class DynamicSlidePanel : UserControl
    {
        List<Grid> _pages = new List<Grid>();
        int _activePage = 0;
        int _nTotalPages = 0;

        public DynamicSlidePanel(List<UIElement> elements)
        {
            InitializeComponent();

            _nTotalPages = elements.Count;

            for (int i = 0; i < _nTotalPages; i++)
            {
                //Criacao de uma grid (pagina) para colocar cada um dos elementos
                
                Grid grd = new Grid();
                if (i % 2 == 0)
                    grd.Background = Brushes.LightSalmon;
                else
                    grd.Background = Brushes.Beige;
                grd.Children.Add(elements[i]);
                grd.Width = 400;
                grd.Height = 200;

                //Adicona nova coluna à MainGrid
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                //Adiciona a grid (pagina) com o elemento à respectiva coluna na MainGrid
                Grid.SetColumn(grd, i);
                mainGrid.Children.Add(grd);

            }
            UpdatePagingControls();
        }

        private void btnNextPage_Click(object sender, RoutedEventArgs e)
        {
            _activePage++;

            DoubleAnimation dAnim = new DoubleAnimation();
            dAnim.SetValue(Storyboard.TargetNameProperty, "mainGrid");
            dAnim.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(Canvas.Left)"));
            dAnim.To = -(double)mainGrid.Children[_activePage - 1].GetValue(Canvas.ActualWidthProperty) * _activePage;
            dAnim.From = (double)mainGrid.GetValue(Canvas.LeftProperty);
            dAnim.Duration = TimeSpan.FromSeconds(0.5);

            Storyboard sb = new Storyboard();
            sb.Children.Add(dAnim);
            sb.Begin(this);

            UpdatePagingControls();
        }

        private void btnPreviousPage_Click(object sender, RoutedEventArgs e)
        {
            _activePage--;

            DoubleAnimation dAnim = new DoubleAnimation();
            dAnim.SetValue(Storyboard.TargetNameProperty, "mainGrid");
            dAnim.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(Canvas.Left)"));
            dAnim.To = -(double)mainGrid.Children[_activePage].GetValue(Canvas.ActualWidthProperty) * _activePage;
            dAnim.From = (double)mainGrid.GetValue(Canvas.LeftProperty);
            dAnim.Duration = TimeSpan.FromSeconds(0.5);

            Storyboard sb = new Storyboard();
            sb.Children.Add(dAnim);
            sb.Begin(this);

            UpdatePagingControls();
        }

        private void UpdatePagingControls()
        {
            tbPageNumber.Text = string.Format("Page {0} / {1}", _activePage + 1, _nTotalPages);
            btnPreviousPage.IsEnabled = !(_activePage == 0);
            btnNextPage.IsEnabled = !(_activePage == _nTotalPages - 1);
        }
    }

MainWindow

No Xaml so tem a rootGrid

public MainWindow()
        {
            InitializeComponent();
            List<UIElement> list = new List<UIElement>();
            Rectangle rect = new Rectangle();
            rect.Fill = Brushes.Black;
            rect.Width = 50;
            rect.Height = 50;
            Rectangle rect2 = new Rectangle();
            rect2.Fill = Brushes.Black;
            rect2.Width = 50;
            rect2.Height = 50;
            Rectangle rect3 = new Rectangle();
            rect3.Fill = Brushes.Black;
            rect3.Width = 50;
            rect3.Height = 50;

            list.Add(rect);
            list.Add(rect2);
            list.Add(rect3);

            DynamicSlidePanel UC = new DynamicSlidePanel(list);

            rootGrid.Children.Add(UC);

        }

Share this post


Link to post
Share on other sites
Mlourenco

O problema não é o UserControl,

O problema é que neste caso tou a definir o tamanho da grid.

                grd.Width = 400;
                grd.Height = 200;

Mas queria que esta grid tivesse o tamanho da minha janela, ou o tamanho do containner onde eu colocar o UserControl. Se nao definir estes tamanhos da grid, esta fica com o tamanho minimo possivel consoante o que colocar la dentro, no exemplo acima como na MainWindow estou a enviar rectangulos de 50x50 a grid fica com width de 50.

Por norma as grids que nao defines o tamanho ajustam-se ao tamanho disponivel, mas como esta dentro de um canvas ja nao funciona dessa forma.

Estou aberto a sugestões de todos os tipos, nem que tenha que implementar isto tudo de raiz, o meu objectivo é mm ter um userControl que se adapte.

Share this post


Link to post
Share on other sites
Mlourenco

Acho que ja tentei algo do genero, mas quer o Canvas, quer a rootGrid, quer o proprio UserControl, têm o Width = NaN, e o ActualWidth = 0.0

Se eu conseguisse apanhar o espaço que o UserControl ocupa já conseguia dar a volta a isto.

Tentei uma abordagem entretanto que me ja resolve o problema para alguns casos, que é passar nos argumentos do construtor do UserControl, a largura e a altura do Containner/Window em que estou a colocar o UserControl. Mas julgo que tenha de existir uma forma de conseguir fazer isto mais dinamico....

Obrigado pelas sugestões

Share this post


Link to post
Share on other sites
saramgsilva

Acho que ja tentei algo do genero, mas quer o Canvas, quer a rootGrid, quer o proprio UserControl, têm o Width = NaN, e o ActualWidth = 0.0

Se eu conseguisse apanhar o espaço que o UserControl ocupa já conseguia dar a volta a isto.

Tentei uma abordagem entretanto que me ja resolve o problema para alguns casos, que é passar nos argumentos do construtor do UserControl, a largura e a altura do Containner/Window em que estou a colocar o UserControl. Mas julgo que tenha de existir uma forma de conseguir fazer isto mais dinamico....

Obrigado pelas sugestões

A questão de teres o canvas & grid se calhar vai-te dar alguns problemas....não sei, se estarás a fazer a melhor abordagem ao problema.

Share this post


Link to post
Share on other sites
Mlourenco

realmente o canvas é que estraga tudo... Mas para fazer a animação necessito dele.

Na pratica tenho uma grid (mainGrid) onde vou adicionando dinamicamente colunas e adicionando a cada coluna uma grid com cada elemento da minha lista

e o que quero que fique visivel por exemplo inicialmente será a coluna 1, e quando mudo de pagina a coluna 2 ja tem a grid preenchida, com a animacao mudo o left do canvas igual ao tamanho da coluna 1 que fica escondida e trazendo para a frente a coluna 2.

Preciso se calhar de tentar uma abordagem diferente em vez do canvas, mas para fazer esta transição lateral nao tou a ver uma forma melhor.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.