asp.net 3.5 Я "получаю" это? - PullRequest
0 голосов
/ 25 февраля 2009

Я изучаю ASP.NET 3.5 & C #, используя Visual Studio 2008. Большая часть материала, который я изучаю, - через MSDN. Я пытаюсь разработать веб-страницу, которая позволит пользователю создать персонажа для использования в RPG-игре. Пользователь должен иметь возможность распределять атрибуты, покупать предметы и т. Д. Когда пользователь завершит работу, сайт отформатирует печатную таблицу символов с данными пользователя.

Теперь я все еще обнимаю все вокруг и хотел бы знать, нахожусь ли я на правильном пути - если бы кто-нибудь хотел бы посмотреть на то, что у меня есть, и прокомментировать, что было бы здорово. Меня интересует все, что я делаю неправильно или неэффективно, плохой дизайн, дрянной код и способы, которые я могу улучшить. Но в основном я просто хочу знать, нахожусь ли я на правильном пути и не злоупотребляю ли технологией.

Ниже приведен код, который у меня есть. Это позволяет пользователю распределять определенное количество баллов по 4 показателям.

Главная страница:

<%@ Page Language="C#" 
    AutoEventWireup="true"  
    CodeFile="Default.aspx.cs" 
    Inherits="_Default" 
    enableSessionState="true"
%>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <!-- MPCP/Bod/Evasion/Masking/Sensor -->


        <asp:Label ID="MPCP_Rating" runat="server" Text="" ></asp:Label>
        <br /> <br />
        <asp:Label ID="PersonaPool" runat="server" Text="" ></asp:Label>
        <br /> <br />

        <!-- TODO: Format into table -->
        Bod:
        <asp:TextBox ID="Bod" runat="server" ontextchanged="Bod_TextChanged" 
            width="25px">0</asp:TextBox> 
        <asp:Button ID="BodInc" runat="server" Text="+" 
            OnClick="Bod_Inc" />
        <asp:Button ID="BodDec" runat="server" Text="-"
            OnClick="Bod_Dec"/>
        <br /> <br />

        Evasion:
        <asp:TextBox ID="Evasion" runat="server" ontextchanged="Evasion_TextChanged"
            width="25px">0</asp:TextBox>
        <asp:Button ID="EvasionInc" runat="server" Text="+" 
            OnClick="Evasion_Inc" />
        <asp:Button ID="EvasionDec" runat="server" Text="-" 
            OnClick="Evasion_Dec" /> 
        <br /> <br />

        Masking:
        <asp:TextBox ID="Masking" runat="server" ontextchanged="Masking_TextChanged"
            width="25px">0</asp:TextBox>
        <asp:Button ID="MaskingInc" runat="server" Text="+" 
            OnClick="Masking_Inc" />
        <asp:Button ID="MaskingDec" runat="server" Text="-" 
            OnClick="Masking_Dec" /> 
        <br /> <br />

        Sensor:
        <asp:TextBox ID="Sensor" runat="server" ontextchanged="Sensor_TextChanged"
            width="25px">0</asp:TextBox>
        <asp:Button ID="SensorInc" runat="server" Text="+" 
            OnClick="Sensor_Inc" />
        <asp:Button ID="SensorDec" runat="server" Text="-" 
            OnClick="Sensor_Dec" /> 
        <br /> <br />
        <asp:Button ID="Submit" runat="server" Text="Submit" />

    </div>
    </form>
</body>
</html>

Code-Behind:

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
    private DeckData deck;

    public _Default()
    {
    }

    // Page events
    protected void Page_Load(object sender, EventArgs e)
    {
        deck = (DeckData)(System.Web.HttpContext.Current.Session["Deck"]);
        MPCP_Rating.Text = "MPCP Rating: " + deck.MPCP.ToString();
        UpdateAvailPersona();
    }

    protected void Unload(object sender, EventArgs e)
    {
    }

    // Helper functions
    protected void ChangeAttribute(DeckData.Attributes atr, bool inc)
    {
        if (inc == true) 
            deck.IncAttribute(atr); 
        else  
            deck.DecAttribute(atr); 

        UpdateAvailPersona();

        switch (atr)
        {
            case DeckData.Attributes.Bod:
                Bod.Text = deck.Bod.ToString();
                break;
            case DeckData.Attributes.Evasion:
                Evasion.Text = deck.Evasion.ToString();
                break;
            case DeckData.Attributes.Masking:
                Masking.Text = deck.Masking.ToString();
                break;
            case DeckData.Attributes.Sensor:
                Sensor.Text = deck.Sensor.ToString();
                break;
        }
    }

    protected void UpdateAvailPersona()
    {
        PersonaPool.Text = "Persona Pool: " + deck.PersonaMax.ToString() +
            " / " + (deck.CalculateAvailPersona()).ToString();
    }

    // Control Events 
    protected void Bod_Dec(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Bod, false);
    }

    protected void Bod_Inc(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Bod, true);
    }

    protected void Evasion_Dec(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Evasion, false);
    }

    protected void Evasion_Inc(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Evasion, true);
    }

    protected void Masking_Dec(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Masking, false);
    }

    protected void Masking_Inc(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Masking, true);
    }

    protected void Sensor_Dec(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Sensor, false);
    }

    protected void Sensor_Inc(object sender, EventArgs e)
    {
        ChangeAttribute(DeckData.Attributes.Sensor, true);
    }

App-Data (только класс DeckData)

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

/// <summary>
/// Store deck related data and provide methods for adjusting deck data
/// </summary>
public class DeckData
{
    // Set persona multiplier, determines max persona pool
    private const uint _PersonaMultiplier = 3;

    public DeckData(uint MPCP)
    {
        _MPCP = MPCP;
        _Bod = _Evasion = _Masking = _Sensor = 0;

        CalculateMaxPersona();
    }

    // MPCP/Bod/Evasion/Masking/Sensor
    public enum Attributes
    {
        MPCP,
        Bod,
        Evasion,
        Masking,
        Sensor
    }

    private uint _MPCP;
    private uint _Bod;
    private uint _Evasion;
    private uint _Masking;
    private uint _Sensor;

    private uint _PersonaMax;

    /// <summary>
    /// Acessor/Modifiers
    /// </summary>
    public uint MPCP
    {
        get { return _MPCP; }
        set { _MPCP = value; }
    }

    public uint Bod
    {
        get { return _Bod; }
        set { _Bod = value; }
    }

    public uint Evasion
    {
        get { return _Evasion; }
        set { _Evasion = value; }
    }

    public uint Masking
    {
        get { return _Masking; }
        set { _Masking = value; }
    }

    public uint Sensor
    {
        get { return _Sensor; }
        set { _Sensor = value; }
    }

    public uint PersonaMax
    {
        get { return _PersonaMax; }
    }

    /// <summary>
    /// Calculate available persona. Must be called before changing attribs to ensure
    /// persona pool remains valid
    /// </summary>
    /// <returns></returns>
    public uint CalculateAvailPersona()
    {
        // Total deck attribs
        uint attrTotal = _Bod + _Evasion + _Masking + _Sensor;

        return _PersonaMax - attrTotal;
    }

    /// <summary>
    /// Recalculate max persona
    /// </summary>
    private uint CalculateMaxPersona()
    {
        _PersonaMax = _MPCP * _PersonaMultiplier;
        return _PersonaMax;
    }

    /// <summary>
    /// Increment attribute by 1 point 
    /// </summary>
    /// <param name="atr">
    /// The attribute to increment
    /// </param>
    /// <returns>
    /// false if no Persona available
    /// true if attribute successfully incremented
    /// </returns>
    public bool DecAttribute(DeckData.Attributes atr)
    {
        uint availPersona = CalculateAvailPersona();

        if (availPersona == _PersonaMax)
            return false;

        switch (atr)
        {
            case Attributes.MPCP:
                break;
            case Attributes.Bod:
                if (_Bod > 0)               // Check for underflow
                    _Bod -= 1;
                break;
            case Attributes.Evasion:
                if (_Evasion > 0)
                    _Evasion -= 1;
                break;
            case Attributes.Masking:
                if (_Masking > 0)
                    _Masking -= 1;
                break;
            case Attributes.Sensor:
                if (Sensor > 0)
                    _Sensor -= 1;
                break;
        }

        // Check to see if we updated an attribute using cached persona
        if(availPersona != CalculateAvailPersona())
            return true;
        return false;
    }

    public bool IncAttribute(DeckData.Attributes atr)
    {
        uint availPersona = CalculateAvailPersona();

        if (availPersona == 0)
            return false;

        switch (atr)
        {
            case Attributes.MPCP:
                break;
            case Attributes.Bod:
                _Bod += 1;
                break;
            case Attributes.Evasion:
                _Evasion += 1;
                break;
            case Attributes.Masking:
                _Masking += 1;
                break;
            case Attributes.Sensor:
                _Sensor += 1;
                break;
        }

        return true;
    }
}

Спасибо!

Ответы [ 3 ]

3 голосов
/ 25 февраля 2009

Если вы хорошо разбираетесь в html, откажитесь от веб-форм и используйте фреймворк mvc, например asp.net mvc или fubu mvc .

Если вы плохо разбираетесь в html, изучите html, откажитесь от веб-форм и используйте фреймворк mvc.

1 голос
/ 25 февраля 2009

Я только что быстро взглянул на ваш код, и одна вещь, которая бросается в глаза - это количество обратных передач сервера, которые будут задействованы при использовании вашего веб-приложения. Каждое изменение атрибута приведет к тому, что страница будет отправлена ​​обратно на сервер, хотя технически это нормально, что не обеспечивает хорошего взаимодействия с пользователем.

Возможно, вы захотите изучить методы, которые позволят пользователю выполнять все свои модификации, а затем отправлять их все вместе (например, использовать javascript на стороне клиента для поддержки распределения точек атрибута) или альтернативно изучить использование AJAX для асинхронного выполнения. опубликуйте изменения на сервере, обеспечивающие более плавное взаимодействие с пользователем.

РЕДАКТИРОВАТЬ: С моделью, которую вы используете, вы можете использовать событие Command элементов управления Button вместо события Click. Это позволит вам назначить значения CommandName и CommandArgument для каждой кнопки, которые можно восстановить в приведенном ниже коде. Это позволит вам иметь только один метод события для каждой кнопки, который может решить, какой атрибут изменить и как из этих свойств:

<asp:Button ID="BodInc" runat="server" CommandArgument="Increase" 
        CommandName="Bod" oncommand="AttributeButton_Command" Text="+" />
<asp:Button ID="BodDec" runat="server" CommandArgument="Increase" 
        CommandName="Bod" oncommand="AttributeButton_Command" Text="-" />

код позади:

protected void AttributeButton_Command(object sender, CommandEventArgs e)
{
    string attriubuteName = e.CommandName;
    string action = e.CommandArgument;
    // Do stuff
}
0 голосов
/ 25 февраля 2009

Одно из предложений, которое я хотел бы сделать, это посмотреть на использование javascript для увеличения / уменьшения ваших счетчиков в разметке, а затем выполнить обновления вашей модели, используя значения текстовых полей при отправке формы. Как подсказывает @Andy, вы также можете выполнять обновления через AJAX, чтобы уменьшить мерцание видимого пользовательского интерфейса, но я думаю, что, учитывая простые правила, которые у вас есть, выполнение на стороне клиента и однократная отправка сообщений - это путь.

Если вы не хотите, чтобы пользователь вводил числовые значения напрямую, я бы использовал статическое отображение выбранного числа и принудительно использовал кнопки вверх / вниз. Вы можете сделать это похожим на кодовый замок , который допускает выбор вверх / вниз только в том случае, если сумма выбранных в данный момент значений меньше доступной суммы. Конечно, вам нужно обновить код, чтобы убедиться, что максимальные значения не превышены. Запрет прямого ввода пользователя избавит вас от необходимости проверять, что вводятся только числовые значения.

Bod      + [0] =
Evasion  + [0] -
Masking  + [0] -
Sensor   + [0] -
Total       0
Maximum     ?

Вы также хотите подумать о стилизации с использованием классов CSS, а не указывать ширину непосредственно в разметке. Использование CSS поможет вам сохранить единообразный внешний вид во всем приложении и позволят вам быстро и легко изменить этот внешний вид позже благодаря изменениям в вашем CSS, а не в самом коде приложения. .

...