У меня есть приложение, полное страниц и пользовательских элементов управления, многие из которых имеют один или несколько элементов управления "метка" на них для отображения всевозможных сообщений пользователю.
Пример: пользовательский элемент управления AddCompany.ascx, обычно используемый на странице Company.aspx (с Приложением. Основной MasterPage), имеет маркировку на нем, назвал "OutOfCreditLabel" с текстом = "Ошибка: Вы не можете создать новую компанию, как Вы вне кредита". Код проверяет кредит и показывает маркировку в случае необходимости.
Я хочу избавиться от всех этих маркировок повсеместно и просто иметь метод, как который я могу звонить отовсюду
ShowUserMessage("Text goes here");
В предыдущих проектах я реализовал это как единственную маркировку на основной странице и открытом методе в .master.cs - целый, страница имеет строку
<%@ MasterType VirtualPath="~/App.master" %>
в нем это работает - но я не могу заставить это работать над пользовательскими элементами управления (.ascx.cs). Существует ли прием к этому?
Или... Существует ли лучший путь?
Что Вы рекомендовали бы для "глобального" пользовательского метода сообщения, который работает откуда-либо в сайте?
Какие-либо хорошие решения jQuery, возможно?
Обновление
RPM1984 попросил дальнейшее разъяснение, таким образом, я пытаюсь спросить это другой путь:
Мне нужен метод, который я могу назвать из кода - позади (страницы или пользовательского элемента управления), который затем отобразит любой текст, который я указываю пользователю, как то, как stackoverflow говорит Вам о новых ответах на Ваш вопрос при следующем посещении сайта. Это может быть вершиной окна (как ТАК) или где-нибудь на странице, не имеет значения. То, что имеет значение, - то, что это - "глобальный" подход, вместо того, чтобы иметь различные предупреждения JavaScript, и asp:label сорил по любой странице и пользовательскому элементу управления в проекте.
Что-то вроде этого сценарий:
Пользователь нажимает кнопку "Create Widget" на моем "пользовательском элементе управления" менеджера по виджету на моей странице. В конечном счете обработчик:
if (User.IsOutOfCredit)
{
ShowUserMessage("Sorry, you cannot create widgets; you are out of credit.");
}
Это приводит к пользователю, видящему "Извините, что Вы не можете создать виджеты; Вы вне кредита". Или в раскрывающемся или красном тексте на странице где-нибудь или наверху как StackOverflow, что-либо прекрасно
Это имеет смысл?
На главной странице добавьте следующие элементы управления: скрытое поле hfMsg будет содержать сообщение, которое будет отображаться а hfCtrl будет содержать имя элемента управления html, который будет отображать это сообщение, которое в этом примере будет 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" />
ПРИМЕЧАНИЕ: вы можете добавить еще один элемент управления html с другим идентификатором в элемент управления ASCX и использовать его для отображения сообщения вместо lblMsg.
и следующий сценарий:
<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>
ПРИМЕЧАНИЕ: сценарий просто проверяет, есть ли у элемента управления hfMsg сообщение для отображения или нет.
и добавьте следующие два метода на главную страницу:
public void ShowMessage(string control, string message)
{
this.hfCtrl.Value = control;
this.hfMsg.Value = message;
}
public void ClearMessage()
{
this.hfMsg.Value = string.Empty;
}
наконец, вы можете вызвать метод ShowMessage с любой подобной страницы, чтобы отобразить сообщение на главной странице:
Master.ShowMessage("lblMsg","hello world!");
и если у вас есть пользовательский элемент управления, который содержит html-метку (например, lblUserMsg) для отображения сообщения, вы можете просто вызвать ShowMessage и передать ему имя метки:
Master.ShowMessage("lblUserMsg","hello world!");
Я всегда использовал метод SetStatus в MasterPage, чтобы получить доступ к MasterPage изнутри пользовательского элемента управления, просто создайте частное свойство в пользовательском элементе управления (или создайте baseControl класс, от которого наследуются все пользовательские элементы управления):
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");
}
Также, если вы используете элемент управления для хранения статусного сообщения, не забудьте отключить на нем ViewState, иначе вы получите такое же статусное сообщение при обратной передаче, которое вы не делаете. хотеть.
Я искал способ отображения сообщения пользователю в масштабе всего сайта. Я нашел jnotifica . Это похоже на панель stackoverflow в верхней части страницы.
Сайт автора сейчас не работает.
Why not a simple HTML "old-school" extension method? (i.e static method)
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);
}
}
}
Then in your HTML:
<%= HtmlHelpers.Label("sometarget") =>
In your main master page, just import the namespace:
<%@ Import Namespace="Web.Helpers" %>
EDIT after question updated
Ok, i see what you're trying to do now. I would recommend doing it all client-side.
That is, in your main master page, create an initially hidden Then create a helper method somewhere in your web project, rendering out some script. Of course, this is just a guideline. You dont have to use jQuery, you don't have to hardcode the script in the method. You could create a JavaScript function that accepts a string and modifies the HTML of the div, then just call the function. It all depends on how complicated your "message" is, if you need special server controls, internationalization, etc. But this is certainly the easiest way to accomplish what you want (IMHO). <div id="message" style="display: none"></div>
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);
}
Несколько хороших ответов, но ...
MGOwen не упомянул никаких особых требований DHTML (например, обновление со стороны клиента). Так почему бы просто не реализовать простой серверный вспомогательный метод, как он упомянул, найти целевой элемент управления, отображающий сообщение, и отобразить его?
Следующий ShowMessage найдет целевой элемент управления сообщениями, где бы он ни был на странице, а также разрешит любой странице переопределить поведение ShowMessage приложения по умолчанию, если это необходимо.
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
Чтобы использовать, просто поместите буквальный элемент управления на страницу, как в:
<div><asp:Literal
ID="ctlShowMessage" runat="server"
Visible="false"
EnableViewState="false"
/>
</div>
Чтобы использовать, просто вызовите ShowMessage , как в ASPHelper.ShowMessage («недостаточный кредит») . Надеюсь, это то, что вы ищете ... Кейт
Я хотел бы предложить использовать класс для настраиваемой страницы (унаследованный от System.Web.UI.Page) внутри, который добавляет следующее как
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
);
}
и наследует все ваши страницы от этот класс вместо наследования от system.web.ui.page и используйте эту функцию, чтобы показывать свои сообщения своим клиентам
Лично я бы предпочел использовать словарь HttpContext.Current.Items с настраиваемым элементом управления. Подобен подходу Кейта Блустоуна, но не требует произвольно названного элемента управления на странице; это очень ясно дает понять, что происходит. Вы можете легко упаковать его в один класс в качестве серверного элемента управления, но здесь он должен быть помещен в стандартный веб-проект.
Чтобы зарегистрировать сообщение в коде позади:
SiteMessageUtility.Add("Test message");
Для отображения на вашей странице, или главной странице, или где-то еще:
<%@ Register TagPrefix="custom" TagName="SiteMessage" Src="~/Controls/SiteMessage.ascx" %>
<custom:SiteMessage runat="server" />
Вот файлы, которые вам понадобятся:
~ \ 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;
}
}
}
~ \ Controls \ 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);
}
}
Всплывающее окно, безопасное для Javascript. Работает с 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
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
End Class
Конечное пространство имен
Используйте по телефону:
Utilities.WriteJava.Alert("DANGER WILL ROBINSON", Me.Page)