none
Como mover los textblock de un canvas a otro RRS feed

  • Pregunta

  • Buenas, me registro para ver si alguno sabe la solucion a este problema.

    Resulta que estoy haciendo unas aplicaciones y tengo una lista de imagenes y una lista de textblock. Entonces como son 52 elementos y tengo una altura limitada tengo que crear un scrollviewer dentro de un canvas, con un canvas con altura superior dentro para poder usar el scroll.

    A cada Textblock se le añaden 3 eventos y un comportamiento para que cuando lo clickees y arrastres se mueva con el raton, pero al estar dentro de un canvas en el canvas padre no se ve e intento crear un objeto nuevo identico al clickeado y hacerlo hijo del canvas padre pero no me funciona.

    Dejo las partes del codigo xaml y cs:

    <Canvas x:Name="Lienzo" Width="780" Height="650" Background="Wheat">

          <Image Height="474" Canvas.Left="0" Source="" Canvas.Top="63" Width="677" Canvas.ZIndex="-1"/>

           <Image Height="474" Canvas.Left="0" Source="" Canvas.Top="63" Width="677" Canvas.ZIndex="-1"/>

           <ScrollViewer VerticalScrollBarVisibility="Visible" Canvas.Left="677" Height="474" Width="100" Canvas.Top="63" Canvas.ZIndex="1">
                <Canvas Height="780" Name="Textos">
                    <TextBlock x:Name="x" Foreground="#FF000000" FontWeight="Bold" FontSize="12" FontFamily="Raavi" LineStackingStrategy="BlockLineHeight" LineHeight="12" TextAlignment="Left" TextWrapping="Wrap" Text="X" Height="10"/>

                 </Canvas>
            </ScrollViewer>
        </Canvas>
    </UserControl>

    textos es una lista publica de TextBlock

    private void MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e){
                TextBlock item = (TextBlock)sender;
                //lo hacemos hijo de Lienzo
                Lienzo.Children.Add(item);

    Gracias de antemano.




    • Editado Karmak84 viernes, 16 de noviembre de 2012 15:34 Correccion
    viernes, 16 de noviembre de 2012 15:26

Todas las respuestas

  • Hola Karmak

    No se puede establecer un mismo control en 2 contenedores al mismo tiempo, solo se puede mover, eso seria como si hubiese una persona en 2 sitios a la vez ¿quien es quien? (bueno, en fisica cuantica si que es posible ;).

    Si explicas lo que quieres hacer exactamente, te podremos ofrecer soluciones alternativas, ya que lo que quieres hacer tiene pinta de ser una plantilla, algo como esto:

    http://www.c-sharpcorner.com/uploadfile/mahesh/listview-in-wpf/


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/

    martes, 20 de noviembre de 2012 8:12
  • Lo que intento hacer es coger un texto dentro de un scrollviewer y arrastralo a una imagen que esta fuera de él y que se situe encima de la imagen. Lo he intentado con ZIndex y sigue quedandose abajo. La estructura es:

    <Canvas>

         <imagen>

         <scrollviewer>

                <Canvas>

                       <Texto>

                 </Canvas>

         </scrollviewer>

    </canvas>

    Lo que intento es mover el texto de posicion en la gerarquia de nodos, haciendolo hijo del primer canvas, pero sigue manteniendolo como hijo del segundo canvas.

    Seria como situar las partes de una imagen por su nombre y los nombres aparecen al lado y se tienen que arrastrar a su posicion correcta.

    martes, 20 de noviembre de 2012 10:07
  • Hola Karmak.

    De la forma en la que implementas el codigo XAML se complica bastante, ya que el remitente del evento siempre sera el elemento canvas principal. yo lo implementaria de la siguiente forma, aunque la lista de textos yo la insertaria en un listBox, pero te pongo el ejemplo con los canvas:

        <Grid Name="MainGrid" Background="Wheat">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" ></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            
            <!-- Lienzo -->
            <Canvas Grid.Column="0" x:Name="Lienzo" Background="Wheat" PreviewMouseLeftButtonUp="canvas_PreviewMouseLeftButtonUp" 
                    PreviewMouseMove="canvas_PreviewMouseMove" PreviewMouseLeftButtonDown="canvas_PreviewMouseLeftButtonDown">
    
                <Image Height="474" Source="img/Desert.jpg" Width="677" />
                <Image Height="474" Source="img/Lighthouse.jpg" Width="677" />
            </Canvas>
    
            <!-- Textos -->
            <ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Visible" Height="474" Width="100" >
                <Canvas Background="Wheat" Height="780" Name="Textos" PreviewMouseLeftButtonDown="canvas_PreviewMouseLeftButtonDown" 
                        PreviewMouseMove="canvas_PreviewMouseMove" PreviewMouseLeftButtonUp="canvas_PreviewMouseLeftButtonUp" >
                    <TextBlock x:Name="txt_1" Canvas.Top="10" Foreground="#FF000000" TextAlignment="Left" TextWrapping="Wrap" Text="asdfasdfasdf1" Height="20"/>
                    <TextBlock x:Name="txt_2" Canvas.Top="40" Foreground="#FF000000" TextAlignment="Left" TextWrapping="Wrap" Text="asdfasdfasdf2" Height="20"/>
                    <TextBlock x:Name="txt_3" Canvas.Top="70" Foreground="#FF000000" TextAlignment="Left" TextWrapping="Wrap" Text="asdfasdfasdf3" Height="20"/>
                    <TextBlock x:Name="txt_4" Canvas.Top="100" Foreground="#FF000000" TextAlignment="Left" TextWrapping="Wrap" Text="asdfasdfasdf4" Height="20"/>
                </Canvas>
            </ScrollViewer>
        </Grid>

    de esta forma, los canvas estan separados y cada uno procesara los eventos con el mismo como remitente, con lo cual se pueden distinguir. Ademas observa que establezco el color de fondo en los canvas por que si no no funcionan los eventos.

    en el codigo .cs se registran los eventos para mover los textos:

     /// <summary>
        /// Lógica de interacción para MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            FrameworkElement m_element;
    
            /// <summary>
            /// Constructor por defecto de la clase
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// Evento ocurrido en la previsualizacion de pulsar el boton izquierdo en algun canvas
            /// </summary>
            /// <param name="sender">objeto remitente</param>
            /// <param name="e">argumentos del evento</param>
            private void canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                // obtener el UIElement del texto
                m_element = e.Source as FrameworkElement;
            }
    
            /// <summary>
            /// Evento ocurrido en la previsualizacion de liberar el boton izquierdo en algun canvas
            /// </summary>
            /// <param name="sender">objeto remitente</param>
            /// <param name="e">argumentos del evento</param>
            private void canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                // obtener el UIElement
                m_element = null;
            }
    
            /// <summary>
            /// Evento ocurrido en la previsualizacion de click izquierdo del boton en algun canvas
            /// </summary>
            /// <param name="sender">objeto remitente</param>
            /// <param name="e">argumentos del evento</param>
            private void canvas_PreviewMouseMove(object sender, MouseEventArgs e)
            {
                // verificar que existe un texto seleccionado
                if (null == m_element) return;
    
                // obtener el canvas con el cursor
                Canvas canvas = sender as Canvas;
                // obtener el canvas padre del elemento
                Canvas parentElement = m_element.Parent as Canvas;
    
                // si son diferentes, se cambia de padre al texto
                if (parentElement != canvas)
                {
                    parentElement.Children.Remove(m_element);
                    canvas.Children.Add(m_element);
                }
    
                // establer la posicion del raton en el nuevo padre
                m_element.SetValue(Canvas.LeftProperty, e.GetPosition(canvas).X);
                m_element.SetValue(Canvas.TopProperty, e.GetPosition(canvas).Y);
    
            }
        }

    y con esto podrias mover los textos por donde quieras.

    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/

    martes, 20 de noviembre de 2012 13:33
  • PreviewMouseLeftButtonDown me da error, me dice que el miembro no es reconocido o no es accesible. Estoy trabajando con el expresion blen 4.
    jueves, 22 de noviembre de 2012 14:39
  • Hola Karmak.

    ¿estas trabajando con WPF?

    Si, de momento para wpf/silverlight solo puedes usar Expression 4


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/


    viernes, 23 de noviembre de 2012 7:21
  • No, estoy trabajando en silverlight 4
    viernes, 23 de noviembre de 2012 9:34
  • Hola Karmak.

    Si, el codigo que he puesto es para WPF, para silverlight tienes que hacer algunos cambios.

    1.- la clase con el codigo tiene que heredar de 'UserControl' en lugar de 'window'

    2.- a los eventos de raton, se debe eliminar la palabra 'preview' ya que no existe la previsualizacion en sivlerlight, de modo que un evento 'PreviewMouseMove' se quedaria como 'MouseMove'

    3.- en el codigo del evento MouseLeftButtonDown, se debe cambiar 'e.Source' por 'e.OriginalSource'.

    Con estas modificaciones tiene que funcionar en silverlight.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/


    lunes, 26 de noviembre de 2012 7:30