11

我正在尝试使用带有 C# 的 ASP.NET 开发一个多语言网站我的问题是:我想让我的 MasterPage 支持语言之间的切换,但是当我将“InitializeCulture()”放在 masterpage.cs 中时,我得到了这个错误。

这是我的代码:

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

}
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
    if (e.Day.IsToday)
    {
        e.Cell.Style.Add("background-color", "#3556bf");
        e.Cell.Style.Add("font-weight", "bold");
    }
}
Dictionary<string, System.Globalization.Calendar> Calendars =
    new Dictionary<string, System.Globalization.Calendar>()
    {
        {"GregorianCalendar", new GregorianCalendar()},
        {"HebrewCalendar", new HebrewCalendar()},
        {"HijriCalendar", new HijriCalendar()},
        {"JapaneseCalendar", new JapaneseCalendar()},
        {"JulianCalendar", new JulianCalendar()},
        {"KoreanCalendar", new KoreanCalendar()},
        {"TaiwanCalendar", new TaiwanCalendar()},
        {"ThaiBuddhistCalendar", new ThaiBuddhistCalendar ()}
    };

protected override void InitializeCulture()
{
    if (Request.Form["LocaleChoice"] != null)
    {
        string selected = Request.Form["LocaleChoice"];
        string[] calendarSetting = selected.Split('|');
        string selectedLanguage = calendarSetting[0];

        CultureInfo culture = CultureInfo.CreateSpecificCulture(selectedLanguage);

        if (calendarSetting.Length > 1)
        {
            string selectedCalendar = calendarSetting[1];
            var cal = culture.Calendar;
            if (Calendars.TryGetValue(selectedCalendar, out cal))
                culture.DateTimeFormat.Calendar = cal;
        }

        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
    base.InitializeCulture();
}
}

如何创建基类?

4

2 回答 2

14

该方法InitializeCulture()仅存在于Page类中,而不存在于MasterPage类中,这就是您收到该错误的原因。

要解决此问题,您可以创建一个BasePage所有特定页面都继承的:

  1. 创建一个新类(不是 Webform),调用它BasePage,或者任何你想要的。
  2. 使其继承System.Web.UI.Page
  3. 让所有其他页面继承BasePage.

这是一个例子:

public class BasePage : System.Web.UI.Page
{
    protected override void InitializeCulture()
    {
        //Do the logic you want for all pages that inherit the BasePage.
    }
}

特定页面应如下所示:

public partial class _Default : BasePage //Instead of it System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Your logic.
    }

    //Your logic.
}
于 2012-08-20T13:30:52.277 回答
9

有一个替代解决方案不需要您创建 BasePage。

“文化”的问题在于它在页面生命周期的早期设置,因此该Page.InitializeCulture事件是页面上的早期事件之一(如果不是唯一的),我们可以在其中连接以更改Thread.CurrentThread.CurrentUICulture. 但是如果我们更早地这样做,只要请求在服务器上开始。

我对每个请求调用Application_BeginRequest的文件事件执行此操作。Global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
  HttpCookie cookie = Request.Cookies["langCookie"];
  if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
  {
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value);
  }
}

在那里,我检查是否存在包含我想要使用的文化的 cookie。如果没有 cookie,则将使用默认区域性。

要更改我的应用程序的语言,我只需要一个控件来更改客户端的 cookie 值,然后对服务器进行简单的回发。这种控制是在内容页还是母版页上都没有关系,它甚至不需要服务器端的任何代码,因为所有的处理都是在上面的方法上完成的,并且cookie被设置为甚至在页面发布之前的客户端。

我使用了一个简单的 LinkBut​​ton(其样式为墨西哥国旗),但您可以使用任何其他在单击/更改时执行回发的控件。

<asp:LinkButton ID="btnSpanish" runat="server" OnClientClick="SetLanguageCookie('es')" CausesValidation="false" CssClass="mxFlag" />

在此按钮回传到服务器之前,它会运行客户端单击事件,该事件会更新我要设置的 cookie 值,瞧!

我有在母版页头部部分设置 cookie 的 javascript 代码:

function SetLanguageCookie(selectedLanguage) {
  var expDate = new Date();
  expDate.setDate(expDate.getDate() + 20); // Expiration 20 days from today
  document.cookie = "langCookie=" + selectedLanguage + "; expires=" + expDate.toUTCString() + "; path=/";
};

就是这样!!Thread.CurrentThread.CurrentUICulture得到更改,不需要BasePage类也不需要覆盖该方法Page.InitializeCulture。甚至还有一个副作用,即选择的语言会在后续访问时被记住,因为它存储在 cookie 中。

如果您想使用 aDropDownList而不是 a LinkButton,只需确保设置AutoPostBack="true"and,因为 没有OnClientChanged属性DropDownList,您必须硬编码 上的onchange属性DropDownList并将所选值传递给相同的 javascript 函数。

<asp:DropDownList ID="ddlLanguage" runat="server" AutoPostBack="true" onchange="SetLanguageCookie(this.options[this.selectedIndex].value)">
  <asp:ListItem Text="English" Value="en" />
  <asp:ListItem Text="Español" Value="es" />
  <asp:ListItem Text="Français" Value="fr" />
</asp:DropDownList>

但是,该onchange属性不是属性的一部分DropDownList,因为DropDownList是该控件的模拟控件<select>,因此该属性只是在呈现时“按原样”放置,并且在回发机制代码之前呈现。这是上面呈现的 HTML DropDownList

<select name="ctl00$cph1$ddlLanguage" onchange="SetLanguageCookie(this.options[this.selectedIndex].value);setTimeout(&#39;__doPostBack(\&#39;ctl00$cph1$ddlLanguage\&#39;,\&#39;\&#39;)&#39;, 0)" id="cph1_ddlLanguage">
  <option value="en">English</option>
  <option value="es">Español</option>
  <option value="fr">Français</option>
</select>

希望有人发现这种方法和我一样有用。:)

于 2016-03-10T23:20:00.917 回答