2010-07-27 9 views
8

Tengo una aplicación llena de páginas y controles de usuario, muchos de los cuales tienen uno o más controles de etiqueta para mostrar varios mensajes diferentes al usuario.¿Recomendaciones para una buena forma de mostrar mensajes de usuario en asp.net?

Ejemplo: el control de usuario AddCompany.ascx, normalmente usado en la página Company.aspx (con App.Master MasterPage) tiene una etiqueta en que llamó "OutOfCreditLabel" con Text = "Error: No se puede crear un nuevo compañía, ya que está sin crédito ". El código verifica el crédito y muestra la etiqueta si es necesario.

quiero para deshacerse de todas estas etiquetas por todo el lugar y sólo tiene un método que pueda llamar desde cualquier lugar como

ShowUserMessage("Text goes here"); 

En proyectos anteriores He implementado esto como una sola etiqueta en el maestro página y método público en los .master.cs - siempre y cuando la página tiene la línea

<%@ MasterType VirtualPath="~/App.master" %> 

en ella, esto funciona - pero no puedo conseguir que funcione en controles de usuario (.ascx.cs) . Hay un truco para esto?

O ... ¿Hay una manera mejor?

¿Qué recomendarías para un método de mensaje de usuario "global" que funciona desde cualquier parte del sitio?

¿Alguna buena solución jQuery, tal vez?

actualización
RPM1984 ha pedido más aclaraciones, por lo que estoy tratando de hacer esta otra manera:

Necesito un método que pueda llamar desde el código subyacente (de una página o un control de usuario) que luego mostrará el texto que especifique para el usuario, por ejemplo, cómo stackoverflow le informa sobre nuevas respuestas a su pregunta la próxima vez que visite el sitio. Puede estar en la parte superior de la ventana (como SO) o en algún lugar de la página, no importa. Lo que importa es que se trata de un enfoque "global", en lugar de tener varias alertas de javascript y etiquetas asp: desparramadas sobre cada otra página y el control del usuario en el proyecto.

Algo parecido a este escenario:

Un usuario hace clic en el botón "Crear widget" en mi control de usuario "gestor de widgets" en mi página. En el controlador de eventos es:

if (User.IsOutOfCredit) 
{ 
    ShowUserMessage("Sorry, you cannot create widgets; you are out of credit."); 
} 

Esto se traduce en que el usuario vea "Lo siento, no se puede crear widgets, que están fuera de crédito." Ya sea en un texto emergente o rojo en la página en algún lugar o en la parte superior como StackOverflow, todo está bien

¿Eso tiene sentido?

Respuesta

1

¿Por qué no un simple método de extensión HTML "old-school"? (yo.e método estático)

namespace Web.Helpers 
{ 
    public class HtmlHelpers 
    { 
     public static string Label(string target) 
     { 
       var dynamicText = SomeWhere.GetSomeCoolText(); 
       return String.Format("<label for='{0}'>{1}</label>", target, dynamicText); 
     } 
    } 
} 

Luego, en el código HTML:

<%= HtmlHelpers.Label("sometarget") => 

En su página principal maestro, simplemente importar el espacio de nombres:

<%@ Import Namespace="Web.Helpers" %> 

EDITAR tras pregunta actualiza

Ok, veo lo que estás tratando de hacer ahora. Yo recomendaría hacerlo todo del lado del cliente.

Eso es, en su página principal maestro, cree un principio escondido <div> con un identificador único:

<div id="message" style="display: none"></div> 

A continuación, cree un método de ayuda en alguna parte de su proyecto web, lo que hace a cabo una secuencia de comandos.

public void DisplayMessage() 
{ 
    string message = SomeWhere.GetSomeCoolText(); 
    StringBuilder script = new StringBuilder(); 
    script.AppendFormat("$('message').show().append("<span>{0}</span>")", message); 
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), script.ToString(), true); 
} 

Por supuesto, esto es solo una guía. No tiene que usar jQuery, no tiene que codificar el script en el método. Puede crear una función de JavaScript que acepte una cadena y modifique el código HTML del div, luego simplemente llame a la función.

Todo depende de lo complicado que es su "mensaje", si necesita controles de servidor especiales, internacionalización, etc.

pero esto es sin duda la forma más fácil de lograr lo que desea (en mi humilde opinión).

+0

Gracias, este es un enfoque interesante, pero parece que esto solo pondrá algo de texto en la página (todo el tiempo). Necesito algo que pueda usar con una declaración "if" en el código subyacente; si se cumplen ciertas condiciones, enseño el mensaje. Esto no funcionará para mí, ¿o sí? – MGOwen

+0

Ok, estoy un poco confundido en cuanto a lo que estás tratando de hacer. para ShowUserMessage ("El texto va aquí"); ¿Qué es "el texto va aquí" y cuál es el resultado esperado de ShowUserMessage? – RPM1984

+0

OK, aclaración agregada a la pregunta. – MGOwen

1

En la página maestra añadir los siguientes controles: el campo oculto hfMsg llevará a cabo el mensaje que se mostrará y la hfCtrl sostendrá el nombre del control HTML que mostrará este mensaje que será en este ejemplo lblMsg .

<label id="lblMsg" style="background-color:Yellow; border:solid 1px; width:200px;height:100px;display:none;"></label>  
    <asp:HiddenField ID="hfMsg" runat="server" /> 
    <asp:HiddenField ID="hfCtrl" runat="server" /> 

NOTA: puede añadir otro control HTML con un ID diferente en un control ASCX y utilizarlo para mostrar el mensaje en lugar del lblMsg.

y la escritura siguiente:

<script language="javascript" type="text/javascript"> 
    var msg = $('#<%= hfMsg.ClientID %>').attr("value"); 
    var ctrl = $('#<%= hfCtrl.ClientID %>').attr("value"); 

    if (msg != undefined && msg != "") { 
     $("#" + ctrl).html(msg);    
     $("#" + ctrl).show(); 
    } 
    else { 
     $("#" + ctrl).hide(); 
    } 
</script> 

NOTA: el guión simplemente comprueba para ver si el control hfMsg tiene un mensaje para mostrar o no.

y añadir los dos siguientes métodos para la página maestra:

public void ShowMessage(string control, string message) 
{ 
    this.hfCtrl.Value = control; 
    this.hfMsg.Value = message; 
} 

public void ClearMessage() 
{ 
    this.hfMsg.Value = string.Empty; 
} 

Por último, puede llamar al método ShowMessage desde cualquier página como esta para mostrar un mensaje en la página maestra:

Master.ShowMessage("lblMsg","hello world!"); 

y si tiene un control de usuario que contiene una etiqueta html (por ejemplo, lblUserMsg) para mostrar el mensaje, simplemente puede llamar a ShowMessage y pasarle el nombre de la etiqueta:

Master.ShowMessage("lblUserMsg","hello world!"); 
+0

Esto es inteligente, pero ¿cómo puedo acceder a ** Master ** desde un control de usuario? Intenté esto. PAGE.Master y la línea VirtualPath que funciona para páginas, pero no funcionan en controles de usuario (.ascx.cs). – MGOwen

+0

puede crear una clase de utilidad y agregarle este método: public static void ShowMessage (Página p, cadena msg, string ctrl) { (p.Master.FindControl ("hfCtrl") como HiddenField) .Value = ctrl ; (p.Master.FindControl ("hfMsg") como HiddenField) .Value = msg; } y llámalo a cualquier parte. y en el control de usuario, llámelo de esta manera: Util.ShowMessage (this.Page, "message", "control"); –

1

Estaba buscando una forma de mostrar todo el sitio al usuario. Encontré jnotifica. Es similar a la barra de stackoverflow en la parte superior de la página.

El sitio del autor parece estar inactivo por el momento.

+0

Esto suena perfecto, pero sí, está caído. :( – MGOwen

+1

Esto se puede acceder a través de su página gitHub: http://github.com/lenon/jNotifica. –

1

Tener un método SetStatus en la página maestra siempre es la forma en que lo hice, para acceder a la página maestra desde un control de usuario, simplemente crear una propiedad privada en el control de usuario (o crear una clase baseControl que hereden todos los controles de usuario desde):

private TheNameSpaceOfMyMasterPage.MyMasterPage Master 
{ 
    get { return (TheNameSpaceOfMyMasterPage.MyMasterPage)Page.Master; } 
} 

protected void btnSave_OnClick(object sender, EventArgs e) 
{ 
    // Do your stuff... 

    // Set the Status 
    this.Master.ShowStatus("blah blah blah"); 
} 

Además, si usted está usando un control para mantener el mensaje de estado recuerde desactivar ViewState en él, de lo contrario va a terminar con el mismo mensaje de estado a través de las devoluciones de datos que no desea.

1

algunas buenas respuestas, pero ...

  1. Para Robert W: la página maestra obras impl, pero sí requiere un acoplamiento fuerte (conocimiento de) con el tipo de página principal. Las páginas maestras generalmente deberían afectar el estilo solamente, ¿no? P.ej. Debería poder cambiar las páginas maestras sin romper mi aplicación.
  2. SubPortal: sí, muy inteligente, pero ... muy listo para mí. También tiene un problema de página maestra.
  3. RPM1984: ¡De nuevo, demasiado inteligente para mí!

MGOwen no mencionaron ningún requisito especial DHTML (por ejemplo, actualización del lado del cliente). Entonces, ¿por qué no simplemente implementar un método simple de ayudante del lado del servidor como lo mencionó, encontrar el control objetivo que muestra el mensaje y mostrarlo?

El siguiente ShowMessage encontrará el control del mensaje de destino donde sea que esté en la página, así como también habilitará cualquier página para anular el comportamiento de ShowMessage de la aplicación predeterminada si así lo desea.

public static class ASPHelper { 

    // Defines something that shows a message 
    public interface IShowMessage 
    { 
     void ShowMessage(string msg); 
    } 

    // default implementation: finds a target message display control 
    // wherever it is on the page. 
    static void ShowMessage_Default(string msg) 
    { 
     const string SHOWMESSAGE_CONTROL_ID = "ctlShowMessage"; // or whatever 

     // find the control 
     Page currentPage = HttpContext.Current.CurrentHandler as Page; 
     Control ctlMessage = currentPage.FindControlRecursive(SHOWMESSAGE_CONTROL_ID); 

     if (ctlMessage == null) 
      throw new Exception("ShowMessage control not found!"); 

     Literal ctlMessageLiteral = ctlMessage as Literal; 
     if (ctlMessageLiteral == null) 
      throw new Exception("ShowMessage control must be a Literal!"); 

     // Message control should not implement viewstate -- unneccesary 
     Debug.Assert(ctlMessageLiteral.EnableViewState == false); 

     // show it 
     ctlMessageLiteral.Text = msg; 
     ctlMessageLiteral.Visible = true; 
    } 

    // public version for use across app & in pages 
    static public void ShowMessage(string msg) 
    { 
     // Allow the current page to implement its own way of showing 
     // messages -- provides flexibility. 
     Page currentPage = HttpContext.Current.CurrentHandler as Page; 
     IShowMessage showMessageImpl = currentPage as IShowMessage; 
     if (showMessageImpl != null) 
     { 
      // Show using custom message displayer 
      showMessageImpl.ShowMessage(msg); 
     } 
     else 
     { 
      // static/global/default version 
      ShowMessage_Default(msg); 
     } 
    } 

} // end ASPHelper 

Para usarlo, basta con colocar un control literal en la página, como en:

<div><asp:Literal 
    ID="ctlShowMessage" runat="server" 
    Visible="false" 
    EnableViewState="false" 
    /> 
</div> 

Para usarlo, basta con llamar ShowMessage, como en ASPHelper.ShowMessage ("insuficiencia de crédito"). Esperamos que esto sea lo que estás buscando ... Keith

1

me gustaría sugerir utilizar una clase de página personalizada (Se hereda de System.Web.UI.Page) en el interior que añaden follwing como

protected void AlertError(string ErrorString) 
{ 
    StringBuilder scriptBuidler = 
    new StringBuilder(@"<script type='text/javascript' language='javascript'>"); 
    scriptBuidler.Append(@"alert('"); 
    scriptBuidler.Append(ErrorString); 
    scriptBuidler.Append(@"');"); 
    scriptBuidler.Append(@"</script>"); 
    AjaxControlToolkit.ToolkitScriptManager.RegisterClientScriptBlock 
    (this, typeof(Page), 
    "Patient Detail Not Found", 
    scriptBuidler.ToString(), 
    false 
    ); 
} 

y heredar todas sus páginas de esta clase en lugar de inherinting de system.web.ui.page y utilizar esta función para mostrar sus mensajes a sus clientes

2

Personalmente, prefiero usar el HttpContext.Current. Diccionario de elementos con un control personalizado. Similar al enfoque de Keith Bluestone, pero no requiere un control arbitrariamente nombrado en la página; deja muy claro lo que está pasando. Podría empaquetarlo en una sola clase como control de servidor con la suficiente facilidad, pero aquí debe incluirse en un proyecto web estándar.

Para registrar un mensaje en su código detrás:

SiteMessageUtility.Add("Test message"); 

para mostrar en su página, o en la página principal, o donde sea, en realidad:

<%@ Register TagPrefix="custom" TagName="SiteMessage" Src="~/Controls/SiteMessage.ascx" %> 
<custom:SiteMessage runat="server" /> 

He aquí los archivos que necesitará:
~ \ App_Code \ SiteMessageUtility.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

public static class SiteMessageUtility 
{ 
    public static void Add(string message) 
    { 
     string currMessage = HttpContext.Current.Items["message"] as string; 
     if (currMessage == null) 
     { 
      HttpContext.Current.Items["message"] = message; 
     } 
     else 
     { 
      HttpContext.Current.Items["message"] = currMessage + "<br/>" + message; 
     } 
    } 
} 

~ \ Contr oles \ SiteMessage.aspx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="SiteMessage.ascx.cs" Inherits="Controls_SiteMessage" %> 
<asp:Literal runat="server" ID="message" /> 

~ \ Controls \ SiteMessage.aspx.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

public partial class Controls_SiteMessage : System.Web.UI.UserControl 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 

    protected override void OnPreRender(EventArgs e) 
    { 
     message.Text = (string)HttpContext.Current.Items["message"]; 
     base.OnPreRender(e); 
    } 
} 
1

Javascript emergente seguro. Funciona con Ajax/jQuery.

Namespace Utilities 

''' <summary> 
''' Utility class for injecting JavaScript into pages. Used primarily for throwing a JavaScript alert box, with correct focus. 
''' </summary> 
''' <remarks></remarks> 
Public Class WriteJava 

Región "Subs Públicas"

Public Shared Sub Script(ByVal script As String, ByRef p As Page, Optional ByVal scriptName As String = "") 
     If String.IsNullOrEmpty(scriptName) Then 
      scriptName = GetScriptName(p) 
     End If 
     If Not p.ClientScript.IsStartupScriptRegistered(scriptName) Then 
      ToolkitScriptManager.RegisterStartupScript(p, p.GetType, scriptName, script, True) 
     End If 
    End Sub 

    Public Overloads Shared Sub Alert(ByVal MyAlert As String, ByRef p As Page) 
     Script("alert('" & Format(MyAlert) & "');", p) 
    End Sub 


    Private Shared Function Format(ByVal value As String) As String 
     Return value.Replace("'", "\'").Replace(Chr(13), "\r").Replace(Chr(10), "\n") 
    End Function 

    Private Shared Function GetScriptName(ByVal p As Page) As String 
     Dim i As Integer = p.AppRelativeVirtualPath.LastIndexOf("/") 
     Dim pageName As String = p.AppRelativeVirtualPath.Substring(i + 1) 
     Return pageName 
    End Function 

final de la región

End Class 

Fin Espacio de nombres

Uso llamando:

Utilities.WriteJava.Alert("DANGER WILL ROBINSON", Me.Page) 
1

Levante un evento en el control de usuario, suscríbase al evento desde la página. El controlador de eventos actualiza su propiedad de página personalizada. Parece la menor cantidad de partes móviles.

Cuestiones relacionadas