Как установить цвет в DetailsView на основе значения?

Использование ASP.NET 4 с C#.

У меня есть DetailsView, который я заполняю с помощью кода программной части в C#, в основном привязывая DataTable из SQL Server к DetailsView. Я хотел бы изменить цвет значений в представлении сведений, чтобы положительные значения были зелеными, нули - по умолчанию, а отрицательные значения - красным. Как лучше всего это сделать?

ОБНОВЛЕНИЕ

@Jay Я пробовал этот код:

private System.Drawing.Color GetColorValue(decimal value)
{
    if (value > 0)
        return System.Drawing.Color.Green;
    else if (value < 0)
        return System.Drawing.Color.Red;
    return System.Drawing.Color.White;
}

protected void dtlOpenTrade_DataBound(object sender, EventArgs e)
{
    foreach (BoundField field in dtlOpenTrade.Fields)
    {
        field.ItemStyle.BackColor = GetColorValue((decimal)dtlOpenTrade.DataItem.GetType().GetProperty(field.DataField).GetValue(dtlOpenTrade.DataItem, null));
    }
}

Но я получаю эту ошибку: System.NullReferenceException: Object reference not set to an instance of an object. Есть идеи?

ОБНОВЛЕНИЕ 2

Я решил это с помощью этого кода, есть смысл?

void RenderDetailsViewColour(DetailsView dtl)
{
    foreach (DetailsViewRow row in dtl.Rows)
    {
        if (row.Cells[0].Text != "TradeId")
        {
            row.Cells[1].BackColor = GetColorValue(Convert.ToDecimal(row.Cells[1].Text));
        }
    }           
}

person Mark Allison    schedule 20.06.2011    source источник


Ответы (2)


Это может быть не «лучший способ», но вы можете обработать событие DataBound в представлении сведений, получить ссылку на каждый из содержащихся элементов управления, а затем изменить их цвет в зависимости от значения.

Это грубый пример:

Ваш бизнес-объект:

public class BusinessObject
{
    public decimal ValueOne { get; set; }
    public decimal ValueTwo { get; set; }
    public decimal ValueThree { get; set; }
    public decimal ValueFour { get; set; }
    public decimal ValueFive { get; set; }
}

Разметка DetailsView:

<asp:DetailsView ID="DetailsView" runat="server" AutoGenerateRows="false">
    <Fields>
        <asp:BoundField DataField="ValueOne" HeaderText="One" />
        <asp:BoundField DataField="ValueTwo" HeaderText="Two" />
        <asp:BoundField DataField="ValueThree" HeaderText="Three" />
        <asp:BoundField DataField="ValueFour" HeaderText="Four" />
        <asp:BoundField DataField="ValueFive" HeaderText="Five" />
    </Fields>
</asp:DetailsView>

Подключите событие и привяжите данные в коде программной части:

        this.DetailsView.DataBound += new EventHandler(DetailsView_DataBound);
        this.DetailsView.DataSource = new BusinessObject[] { myBusinessObject };
        this.DetailsView.DataBind();

Напишите процедуру, которая принимает значение и возвращает цвета. Это можно расширить, чтобы вернуть пару значений, таких как фон, цвет и т. Д.

    System.Drawing.Color GetColorValue(decimal value)
    {
        if (value > 0)
        {
            return System.Drawing.Color.Green;
        }
        else if (value < 0)
        {
            return System.Drawing.Color.Red;
        }
        return System.Drawing.Color.White;
    }

Наконец, обработчик события

void DetailsView_DataBound(object sender, EventArgs e)
{
    foreach (BoundField field in this.DetailsView.Fields)
    {
        field.ItemStyle.BackColor = GetColorValue((decimal)
            this.DetailsView.DataItem.GetType()
            .GetProperty(field.DataField)
            .GetValue(this.DetailsView.DataItem, null));
    }
}
person Jay    schedule 20.06.2011
comment
Откуда берется исключение? Я предполагал и просто указывал, что ваши данные представляют собой десятичные дроби. Объект, к которому вы привязываетесь, может быть другим. - person Jay; 20.06.2011
comment
Я использую десятичные дроби, ошибка исходит из field.ItemStyle.BackColor = GetColorValue((decimal)dtlOpenTrade.DataItem.GetType().GetProperty(field.DataField).GetValue(dtlOpenTrade.DataItem, null)); - person Mark Allison; 20.06.2011
comment
В этой строке много чего происходит. Нужно выяснить, какая часть равна нулю. Это также предполагает, что все поля в вашем DetailsView являются BoundFields - person Jay; 20.06.2011
comment
@Jay: Проверьте мое ОБНОВЛЕНИЕ 2. Есть ли смысл? - person Mark Allison; 20.06.2011
comment
Это тоже сработает. Вам просто нужно убедиться, что ваш метод вызывается каждый раз, когда DetailsView привязан к данным. - person Jay; 21.06.2011

Мои мысли были такими же, как у Джея.

Разметка:

        <asp:TemplateField HeaderText="Amount Paid" >
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" Text='<%# Eval("AmountPaid") %>' />
            </ItemTemplate>
        </asp:TemplateField>

Код:

protected void DetailsView1_DataBound(object sender, EventArgs e)
{
    Label objLabel = (Label)DetailsView1.FindControl("Label1");
    if (objLabel != null)
    {
        Decimal decValue = Convert.ToDecimal(objLabel.Text);
        if (decValue > 0)
        {
            objLabel.ForeColor = System.Drawing.Color.Green;
        }
        else if (decValue < 0)
        {
            objLabel.ForeColor = System.Drawing.Color.Red;
        }
    }
}
person pseudocoder    schedule 20.06.2011
comment
Этот способ также будет работать, вам просто нужно убедиться, что каждое поле, которое вы хотите стилизовать, учитывается в вашем методе. Но если вы дойдете до создания шаблона, почему бы просто не оценить стиль прямо из разметки? - person Jay; 21.06.2011