InvalidCastExceptions при установке атрибутов GridViewRow

Я работаю над контекстным меню для элементов в моем GridView, но есть одна серьезная загвоздка. Я не могу понять, как отправить значение PK для строки, по которой щелкнули правой кнопкой мыши, в JQuery, который взаимодействует с моим обработчиком HTTP для обновления базы данных.

По сути, контекстное меню будет состоять из 3 пунктов: «Ответить», «Отметить как прочитанное» и «Удалить». В каждом случае мне нужно, чтобы значение mailid из базы данных было доступно для JQuery, чтобы я мог перенаправить пользователя на страницу, где он может ответить на выбранное письмо, или сообщить обработчику HTTP, какой элемент в базе данных он должен обновить .

Вот мой код:

    protected void gvItems_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            e.Row.Attributes["onClick"] = "getMailDetail(" + DataBinder.Eval(e.Row.DataItem, "mailid") + ")";
            e.Row.Attributes["id"] = DataBinder.Eval(e.Row.DataItem, "mailid");

            Label lblStatus = (Label)e.Row.FindControl("lblStatus");

            if (lblStatus.Text == "unread")
            {
                e.Row.Font.Bold = true;
            }
        }
    }

Я устанавливаю атрибут onClick для строк, чтобы щелчок в любом месте GridViewRow запускал страницу для подробного отображения почты. Я подумал, что могу получить значение mailid таким же образом, используя другой атрибут.

А на .aspx...

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery.contextMenu.js"></script>
<script type="text/javascript">
    function getMailDetail(mailId) {
        $.ajax({
            type: "GET",
            url: '<%= ResolveUrl("~/GetMail.ashx") %>',
            data: { mid: mailId },
            success: function (data) {
                var pnlList = $('#<%= pnlList.ClientID %>');
                var pnlMail = $('#<%= pnlMail.ClientID %>');
                var lblFrom = $('#<%= lblFrom.ClientID %>');
                var lblDate = $('#<%= lblDate.ClientID %>');
                var lblSubject = $('#<%= lblSubject.ClientID %>');
                var lblMessage = $('#<%= lblMessage.ClientID %>');

                lblFrom.text(data.From);
                lblDate.text(data.Date);
                lblSubject.text(data.Subject);
                lblMessage.text(data.Message);

                pnlList.css("display", "none");
                pnlMail.css("display", "block");
            }
        });
    }

    function markRead(mailId) {
        $.ajax({
            type: "POST",
            url: '<%= ResolveUrl("~/MailAction.ashx") %>',
            data: { mid: mailId, act: "markRead" },
            success: window.location = "Inbox.aspx"
        });
    }

    function deleteMail(mailId) {
        $.ajax({
            type: "POST",
            url: '<%= ResolveUrl("~/MailAction.ashx") %>',
            data: { mid: mailId, act: "Delete" },
            success: window.location = "Inbox.aspx"
        });
    }
</script>
<div class="columns">
    <div class="leftcol">
        <a href="Write.aspx" class="button">Compose Message</a>

        <ul>
            <li><a href="SentItems.aspx">Sent Items</a></li>
            <li class="active"><a href="Inbox.aspx">Inbox</a></li>
            <li><a href="DeletedItems.aspx">Deleted Items</a></li>
        </ul>
    </div>

    <div class="rightcol">
        <asp:Panel runat="server" ID="pnlList">
            <div class="rightalign">
                <asp:Label runat="server" ID="lblCount"></asp:Label>
            </div>

            <asp:GridView runat="server" ID="gvItems" DataKeyNames="mailid" 
                AutoGenerateColumns="false" onrowdatabound="gvItems_RowDataBound" 
                Width="100%">
                <Columns>
                    <asp:TemplateField ItemStyle-CssClass="centeralign">
                        <HeaderTemplate>
                            <asp:CheckBox runat="server" ID="chkSelectAll" />
                        </HeaderTemplate>
                        <ItemTemplate>
                            <asp:CheckBox runat="server" ID="chkSelect" />
                        </ItemTemplate>
                    </asp:TemplateField>

                    <asp:TemplateField ItemStyle-CssClass="hidden" HeaderStyle-CssClass="hidden">
                        <ItemTemplate>
                            <asp:Label runat="server" ID="lblStatus" Text='<%# DataBinder.Eval(Container.DataItem, "status") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField ItemStyle-CssClass="hidden" HeaderStyle-CssClass="hidden" DataField="mailid" />
                    <asp:BoundField DataField="firstname" HeaderText="From" SortExpression="firstname" />
                    <asp:BoundField DataField="datesent" HeaderText="Date" SortExpression="datesent" DataFormatString="{0:yyyy/MM/dd HH:mm}" />
                    <asp:BoundField DataField="subject" HeaderText="Subject" SortExpression="subject" />
                </Columns>
            </asp:GridView>
        </asp:Panel>

        <asp:Panel runat="server" ID="pnlMail" cssclass="hidden">
            <p>From: <asp:Label runat="server" ID="lblFrom"></asp:Label><br />
                Sent On: <asp:Label runat="server" ID="lblDate"></asp:Label><br />
                Subject: <asp:Label runat="server" ID="lblSubject"></asp:Label></p>
            <p><asp:Label runat="server" ID="lblMessage"></asp:Label></p>
        </asp:Panel>
    </div>
</div>

<!-- Row Context Menu -->
<ul id="contextmenu" class="contextMenu">
    <li><a href="#reply">Reply</a></li>
    <li><a href="#mread">Mark As Read</a></li>
    <li><a href="#delete">Delete</a></li>
</ul>

<script type="text/javascript">
    $(document.ready(function() {
        $(".dataRow").contextMenu({
            menu: 'contextmenu' },
            function(action, el, pos, mid) {
                contextMenuWork(action, el, pos);
            }
        );
    },
    function contextMenuWork(action, el, pos) {
        var mid = $(el).attr("id");
        switch (action) {
            case "reply":
            {
                window.location = "Reply.aspx?id=" + mid;
                break;
            }
            case "mread":
            {
                markRead(mid);
                break;
            }
            case "delete":
            {
                deleteMail(mid);
                break;
            }
        }
    }
);
</script>

К сожалению, в моем подходе здесь возникла проблема, поскольку я получаю InvalidCastException при назначении атрибута id для недавно связанного GridViewRow:

Невозможно неявно преобразовать тип «объект» в «строку». Существует явное преобразование (вам не хватает приведения?)

Итак, я заменяю эту строку на эту

e.Row.Attributes["id"] = (string)DataBinder.Eval(e.Row.DataItem, "mailid");

И теперь, хотя нет никаких ошибок, о которых Visual Studio может сообщить мне во время разработки, во время выполнения я получаю следующее InvalidCastException:

Невозможно привести объект типа «System.Int32» к типу «System.String».

Я понятия не имею, откуда берется целое число, поэтому я не знаю, как действовать дальше.

Любая помощь будет оценена.


person Ortund    schedule 23.10.2012    source источник
comment
Возможно, что mailid не имеет предполагаемых значений, так как частые опечатки или логические незамеченные ошибки могут привести к вышеперечисленным ситуациям. Не могли бы вы добавить, чтобы посмотреть и проверить, какое значение в DataBinder.Eval(e.Row.DataItem, mailid);   -  person Munawar    schedule 23.10.2012
comment
В моем тестовом случае часы показывают мне ожидаемое значение, поэтому у меня нет причин думать, что в других случаях они будут вести себя иначе. Похоже, что значение имеет тип `object{int}, из которого может исходить вторая ошибка, но разве я не могу использовать .ToString() и целочисленное значение?   -  person Ortund    schedule 23.10.2012


Ответы (1)


Кажется, мне никогда не удавалось получить рабочее приведение значения здесь, поэтому я изменил RowDataBound void на следующее:

    protected void gvItems_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var mailid = DataBinder.Eval(e.Row.DataItem, "mailid");
            e.Row.Attributes["onClick"] = "getMailDetail(" + DataBinder.Eval(e.Row.DataItem, "mailid") + ")";
            e.Row.Attributes["id"] = mailid.ToString();

            Label lblStatus = (Label)e.Row.FindControl("lblStatus");

            if (lblStatus.Text == "unread")
            {
                e.Row.Font.Bold = true;
            }
        }
    }

Объявление нового var и значение DataItem для «mailid», а затем присвоение ему .ToString() исправило все мои проблемы.

person Ortund    schedule 23.10.2012