none
Posicionar UserControl respecto al punto del mouse RRS feed

  • Pregunta

  • Hola

    Esta pregunta es derivada de este otra

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/d9d9f692-c009-4ae2-9c86-315d2a3e6ce4

     

    Como veran me encuentro desarrollando un user control que muestra un popup

    mas alla de eso lo que buscaba es que dentro del usercontrol (en su codebehind) poder especificar cuando se muestre el control, que lo haga en una posicion concreta con respecto al mouse

     

    dentro del control puedo obtener la posicion del puntero

    Point p = Mouse.GetPosition(null);

    pero como se lo asignaria a si mismo (ya que estoy dentro del propio user control) el cambio de posicion o localizacion

    el tema que propeidades como Top o Left no las tengo, imagino porque no esta dentro de un contenedor

     

    la pregunta es se puede? imagino que si porque el control PopUp que trae el propio WPF lo hace

    pero la segunda pregunta seria, como?

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 29 de abril de 2010 20:35

Respuestas

  • Hola Leandro.

     

    Ya que has abierto este post lo comento aqui y comentar que lo que voy a decir esta basado en el post de la creacion del control en:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/d9d9f692-c009-4ae2-9c86-315d2a3e6ce4

    Como el codigo de posicionamiento, es relativo a la posicion del cursor, es bastante facil de transladarlo al control de usuario, se puede poner el siguiente evento en el control de usuario (control popup):

    IsVisibleChanged="mainControl_IsVisibleChanged"

     

    y luego el mismo codigo anterior con pequeñas modificaciones:

     /// <summary>
     /// evento icurrido al mostrarse el control de usuario
     /// </summary>
     /// <param name="sender">objeto remitente</param>
     /// <param name="e">argumentos del evento</param>
     private void mainControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
     {
      // comprobar si se ha echo visible el control
      if (true == (bool)e.NewValue)
      {
      // obtener ventana principal
      Window wnd = Window.GetWindow(this);
      // obtener posicion del raton
      Point pointer = Mouse.GetPosition(wnd);
      // obtener rectangulo que rodea el ultimo caracter de la seleccion (para obtener sus dimensiones)
      Rect rectChar = this.Selection.End.GetCharacterRect(System.Windows.Documents.LogicalDirection.Backward);
    
      double x, y;
      // evaluar posicion donde se mostrara (arriba o debajo de la seleccion)
      // por defecto se muestra arriba
      y = ((pointer.Y - this.Height - rectChar.Height) > 0) ?
       pointer.Y - this.Height - rectChar.Height :
       pointer.Y + rectChar.Height;
    
      // evaluar posicion donde se mostrara (izquierda o derecha)
      // por defecto se muestra hacia la derecha
      x = ((pointer.X + this.Width) < wnd.Width) ?
       pointer.X :
       pointer.X - this.Width;
    
      // establecer el margen correcto al popup
      this.Margin = new Thickness(x, y, 0, 0);
      }
     }

    y luego, al mostrar el control si que es importante asignar la seleccion antes de hacer visible el control:

      // primero asignar la seleccion y luego mostrarlo
      m_popup.Selection = richTextBox1.Selection;
      m_popup.Visibility = System.Windows.Visibility.Visible; 

     

     


    Saludos
    David González
    viernes, 30 de abril de 2010 6:36

Todas las respuestas

  • Hola Leandro.

     

    Ya que has abierto este post lo comento aqui y comentar que lo que voy a decir esta basado en el post de la creacion del control en:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/d9d9f692-c009-4ae2-9c86-315d2a3e6ce4

    Como el codigo de posicionamiento, es relativo a la posicion del cursor, es bastante facil de transladarlo al control de usuario, se puede poner el siguiente evento en el control de usuario (control popup):

    IsVisibleChanged="mainControl_IsVisibleChanged"

     

    y luego el mismo codigo anterior con pequeñas modificaciones:

     /// <summary>
     /// evento icurrido al mostrarse el control de usuario
     /// </summary>
     /// <param name="sender">objeto remitente</param>
     /// <param name="e">argumentos del evento</param>
     private void mainControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
     {
      // comprobar si se ha echo visible el control
      if (true == (bool)e.NewValue)
      {
      // obtener ventana principal
      Window wnd = Window.GetWindow(this);
      // obtener posicion del raton
      Point pointer = Mouse.GetPosition(wnd);
      // obtener rectangulo que rodea el ultimo caracter de la seleccion (para obtener sus dimensiones)
      Rect rectChar = this.Selection.End.GetCharacterRect(System.Windows.Documents.LogicalDirection.Backward);
    
      double x, y;
      // evaluar posicion donde se mostrara (arriba o debajo de la seleccion)
      // por defecto se muestra arriba
      y = ((pointer.Y - this.Height - rectChar.Height) > 0) ?
       pointer.Y - this.Height - rectChar.Height :
       pointer.Y + rectChar.Height;
    
      // evaluar posicion donde se mostrara (izquierda o derecha)
      // por defecto se muestra hacia la derecha
      x = ((pointer.X + this.Width) < wnd.Width) ?
       pointer.X :
       pointer.X - this.Width;
    
      // establecer el margen correcto al popup
      this.Margin = new Thickness(x, y, 0, 0);
      }
     }

    y luego, al mostrar el control si que es importante asignar la seleccion antes de hacer visible el control:

      // primero asignar la seleccion y luego mostrarlo
      m_popup.Selection = richTextBox1.Selection;
      m_popup.Visibility = System.Windows.Visibility.Visible; 

     

     


    Saludos
    David González
    viernes, 30 de abril de 2010 6:36
  • hola

    gracias por la ayuda

    estoy probando lo que me comentas, pero note que aun usando el Margin de user control, no le cambia la ubicacion

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    viernes, 30 de abril de 2010 14:30
  • Hola leandro.

    ¿estas usando un grid como contenedor principal o Canvas?, te lo comento por que para este tipo de cosas son controles diferentes.

    por otra parte yo he añadido el user control como hijo al grid como indica en el codigo, de esta forma me funciona correctamente. 

    En el ultimo codigo que he puesto se posiciona basandose en las dimensiones de la ventana principal.

    NOTA: se debe tener en cuenta que si se usa un grid como referencia o cualquier otro contenedor, se debe de poner ancho y alto al contenedor explicitamente, de no ser asi su ancho y alto siempre van a ser NAN (valor nulo), esto es muy importante ya que es un error muy comun.


    Saludos
    David González
    lunes, 3 de mayo de 2010 7:18
  • hola

    tienes razon estaba desplazandose, solo que habia agregado algunos bordes y el calculo se modifico un poco

    gracias por toda la ayuda


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    lunes, 3 de mayo de 2010 13:16