C# 防止滚动表中的单个列

C# 防止滚动表中的单个列,c#,javascript,asp.net,html,css,C#,Javascript,Asp.net,Html,Css,好了,巫师们,有人知道怎么做 我有一个非常复杂的自定义控件,用于呈现x个用户的可用性信息(可能是1,也可能是100)。 日历呈现控件属性中指定的任何给定日期范围 这意味着控件可能非常长,所有这些数据都呈现为html表 当每个人的名字出现在第一列时,我希望修复该列,并让表的其余部分水平滚动,这样用户可以浏览整个日期范围,但保持人名可见 那么我如何修复表中的第一列,它看起来像下面的代码 <table> <tr><td></td><td col

好了,巫师们,有人知道怎么做

我有一个非常复杂的自定义控件,用于呈现x个用户的可用性信息(可能是1,也可能是100)。 日历呈现控件属性中指定的任何给定日期范围

这意味着控件可能非常长,所有这些数据都呈现为html表

当每个人的名字出现在第一列时,我希望修复该列,并让表的其余部分水平滚动,这样用户可以浏览整个日期范围,但保持人名可见

那么我如何修复表中的第一列,它看起来像下面的代码

<table>
  <tr><td></td><td colspan='31'>Jan</td><td colspan='28'>feb</td>...</tr>
  <tr><td></td><td>1</td><td>2</td><td>3</td> ...<tr/>
  <tr><td>Person 1</td><td></td><td></td><td>Busy</td> ...<tr/>
  <tr><td>Person 2</td><td></td><td>Busy</td><td>Busy</td> ...<tr/>
</table>

一月二日。。。
123 ...
人1Busy。。。
人2BusyBusy。。。
如果有任何帮助,这是一个C#应用程序(asp.net),如果需要,我愿意使用javascript

谢谢大家:)

这是通过CSS和HTML的组合实现的(如下)。令我惊讶的是,即使在IE6上也能以合理的性能工作。令人印象深刻的工作。由于某种原因,Chrome、Opera和Firefox上的滚动条最终位于冻结的列/行下面,但希望这些滚动条足够大,不会有问题

CSS:

JavaScript:

var ieBug = ((document.all) && (!window.opera)); // IE doesn't really handle fixed elements well :)
var fpElement = false;
function fpCW() { return document.documentElement ? document.documentElement.clientWidth : document.clientWidth; }
function fpCH() { return document.documentElement ? document.documentElement.clientHeight : document.clientHeight; }
function fpTopLeft(elementNode, iTop, iLeft) {
    elementNode.style.top = (iTop)+"px";
    elementNode.style.left = (iLeft)+"px";
}
function fpDefaults(elementNode) {
    elementNode.style.position = ieBug ? "absolute" : "fixed";
    fpTopLeft(elementNode,0,0);
    return elementNode;
}
function fpClone(elementNode, cloneZindex) {
    var clone = fpDefaults(elementNode.cloneNode(true));
    clone.style.background = "#fff";
    clone.style.overflow = "hidden";
    clone.style.border = "none";
    clone.style.zIndex = cloneZindex;
    return clone;
}
function fpInitFreezePanes(fpTableElementId, fpTableContainerDivElementId, fpPivotCellId, fpDisableBodyScrollbars) {
    if (fpElement !== false) {
      alert("Page already contains an element with fixed panes.");
    } else {
        var fpTableElement = document.getElementById(fpTableElementId);
        var fpTableContainerDivElement = document.getElementById(fpTableContainerDivElementId);
        var fpPivotCell = document.getElementById(fpPivotCellId);
        if ((!fpTableElement) || (!fpTableContainerDivElement) || (!fpPivotCell)) {
            alert("Unable to find table, container or pivoting cell?");
        } else {
            fpElement = fpTableContainerDivElement;
            if (fpDisableBodyScrollbars) {
                var x = document.getElementsByTagName("body")[0];
                x.style.overflow = "hidden";
                x = document.getElementsByTagName("html")[0];
                x.style.overflow = "hidden";
            }
            fpTableContainerDivElement = fpDefaults(fpTableContainerDivElement);
            fpTableContainerDivElement.style.width = (fpCW()-2)+"px";
            fpTableContainerDivElement.style.height = (fpCH()-2)+"px";
            fpTableContainerDivElement.fpPT = fpPivotCell.offsetTop;
            fpTableContainerDivElement.fpPL = fpPivotCell.offsetLeft;

            var copy1 = fpClone(fpTableContainerDivElement, 4);
            copy1.style.width = (fpTableContainerDivElement.fpPL)+"px";
            copy1.style.height = (fpTableContainerDivElement.fpPT)+"px";
            var copy2 = fpClone(fpTableContainerDivElement, 3);
            copy2.style.width = (fpTableElement.offsetWidth)+"px";
            copy2.style.height = (fpTableContainerDivElement.fpPT)+"px";
            var copy3 = fpClone(fpTableContainerDivElement, 2);
            copy3.style.width = (fpTableContainerDivElement.fpPL)+"px";
            copy3.style.height = (fpTableElement.offsetHeight)+"px";

            fpTableContainerDivElement.style.zIndex = 1;
            fpTableContainerDivElement.appendChild(copy1);
            fpTableContainerDivElement.copy1 = copy1;
            fpTableContainerDivElement.appendChild(copy2);
            fpTableContainerDivElement.copy2 = copy2;
            fpTableContainerDivElement.appendChild(copy3);
            fpTableContainerDivElement.copy3 = copy3;
            fpTableContainerDivElement.repositioning = false;
            fpTableContainerDivElement.oldST = -1;
            fpTableContainerDivElement.oldSL = -1;
            fpTableContainerDivElement.style.overflow = "scroll";

            /* JUST SOME STYLING HERE */
            copy1.style.borderRight = "1px dashed #000";
            copy1.style.borderCollapse = "collapse";
            copy2.style.borderBottom = "1px dashed #000";
            copy2.style.borderCollapse = "collapse";
            copy3.style.borderRight = "1px dashed #000";
            copy3.style.borderCollapse = "collapse";
            /* JUST SOME STYLING HERE */

            // if (ieBug) {
            if (fpTableContainerDivElement.style.setExpression) {
                function fpIeBugFix(elementNode, containerNodeId, arrayOfExpressionsToSet) {
                    for (var i in arrayOfExpressionsToSet) {
                        if (arrayOfExpressionsToSet[i][2]) {
                            elementNode.style.setExpression(arrayOfExpressionsToSet[i][0], arrayOfExpressionsToSet[i][1]+"document.getElementById('"+containerNodeId+"')."+arrayOfExpressionsToSet[i][2]+"+'px'");
                        } else {
                            elementNode.style.setExpression(arrayOfExpressionsToSet[i][0], arrayOfExpressionsToSet[i][1]);
                        }
                    }
                }
                fpIeBugFix(fpTableContainerDivElement.copy3, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"],["marginTop","-","scrollTop"]]);
                fpIeBugFix(fpTableContainerDivElement.copy2, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"],["marginLeft","-","scrollLeft"]]);
                fpIeBugFix(fpTableContainerDivElement.copy1, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"]]);
                fpIeBugFix(fpTableContainerDivElement, fpTableContainerDivElementId, [["width","fpCW()+'px'"],["height","fpCH()+'px'"]]);
                document.recalc(true);
            } else {
                fpElement.onmousemove = fpElement.onscroll = function() {
                    if (!this.repositioning) {
                        this.repositioning = true;
                        var st = this.scrollTop;
                        var sl = this.scrollLeft;
                        if ((this.oldST != st) || (this.oldSL != sl)) {
                            this.oldST = st;
                            this.oldSL = sl;
                            // this.copy3.previousDisplay = this.copy3.style.display;
                            // this.copy3.style.display = "none";
                            this.copy3.style.marginTop = "-"+(st)+"px";
                            // this.copy3.style.display = this.copy3.previousDisplay;
                            // this.copy2.previousDisplay = this.copy2.style.display;
                            // this.copy2.style.display = "none";
                            this.copy2.style.marginLeft = "-"+(sl)+"px";
                            // this.copy2.style.display = this.copy2.previousDisplay;
                        }
                        fpElement.repositioning = false;
                    }
                };
                window.onresize = function() {
                    fpElement.style.width = fpCW()+"px";
                    fpElement.style.height = fpCH()+"px";
                }
            }
        }
    }
}
这是通过CSS和HTML的组合实现的(见下文)。令我惊讶的是,即使在IE6上也能以合理的性能工作。令人印象深刻的工作。由于某种原因,Chrome、Opera和Firefox上的滚动条最终位于冻结的列/行下面,但希望这些滚动条足够大,不会有问题

CSS:

JavaScript:

var ieBug = ((document.all) && (!window.opera)); // IE doesn't really handle fixed elements well :)
var fpElement = false;
function fpCW() { return document.documentElement ? document.documentElement.clientWidth : document.clientWidth; }
function fpCH() { return document.documentElement ? document.documentElement.clientHeight : document.clientHeight; }
function fpTopLeft(elementNode, iTop, iLeft) {
    elementNode.style.top = (iTop)+"px";
    elementNode.style.left = (iLeft)+"px";
}
function fpDefaults(elementNode) {
    elementNode.style.position = ieBug ? "absolute" : "fixed";
    fpTopLeft(elementNode,0,0);
    return elementNode;
}
function fpClone(elementNode, cloneZindex) {
    var clone = fpDefaults(elementNode.cloneNode(true));
    clone.style.background = "#fff";
    clone.style.overflow = "hidden";
    clone.style.border = "none";
    clone.style.zIndex = cloneZindex;
    return clone;
}
function fpInitFreezePanes(fpTableElementId, fpTableContainerDivElementId, fpPivotCellId, fpDisableBodyScrollbars) {
    if (fpElement !== false) {
      alert("Page already contains an element with fixed panes.");
    } else {
        var fpTableElement = document.getElementById(fpTableElementId);
        var fpTableContainerDivElement = document.getElementById(fpTableContainerDivElementId);
        var fpPivotCell = document.getElementById(fpPivotCellId);
        if ((!fpTableElement) || (!fpTableContainerDivElement) || (!fpPivotCell)) {
            alert("Unable to find table, container or pivoting cell?");
        } else {
            fpElement = fpTableContainerDivElement;
            if (fpDisableBodyScrollbars) {
                var x = document.getElementsByTagName("body")[0];
                x.style.overflow = "hidden";
                x = document.getElementsByTagName("html")[0];
                x.style.overflow = "hidden";
            }
            fpTableContainerDivElement = fpDefaults(fpTableContainerDivElement);
            fpTableContainerDivElement.style.width = (fpCW()-2)+"px";
            fpTableContainerDivElement.style.height = (fpCH()-2)+"px";
            fpTableContainerDivElement.fpPT = fpPivotCell.offsetTop;
            fpTableContainerDivElement.fpPL = fpPivotCell.offsetLeft;

            var copy1 = fpClone(fpTableContainerDivElement, 4);
            copy1.style.width = (fpTableContainerDivElement.fpPL)+"px";
            copy1.style.height = (fpTableContainerDivElement.fpPT)+"px";
            var copy2 = fpClone(fpTableContainerDivElement, 3);
            copy2.style.width = (fpTableElement.offsetWidth)+"px";
            copy2.style.height = (fpTableContainerDivElement.fpPT)+"px";
            var copy3 = fpClone(fpTableContainerDivElement, 2);
            copy3.style.width = (fpTableContainerDivElement.fpPL)+"px";
            copy3.style.height = (fpTableElement.offsetHeight)+"px";

            fpTableContainerDivElement.style.zIndex = 1;
            fpTableContainerDivElement.appendChild(copy1);
            fpTableContainerDivElement.copy1 = copy1;
            fpTableContainerDivElement.appendChild(copy2);
            fpTableContainerDivElement.copy2 = copy2;
            fpTableContainerDivElement.appendChild(copy3);
            fpTableContainerDivElement.copy3 = copy3;
            fpTableContainerDivElement.repositioning = false;
            fpTableContainerDivElement.oldST = -1;
            fpTableContainerDivElement.oldSL = -1;
            fpTableContainerDivElement.style.overflow = "scroll";

            /* JUST SOME STYLING HERE */
            copy1.style.borderRight = "1px dashed #000";
            copy1.style.borderCollapse = "collapse";
            copy2.style.borderBottom = "1px dashed #000";
            copy2.style.borderCollapse = "collapse";
            copy3.style.borderRight = "1px dashed #000";
            copy3.style.borderCollapse = "collapse";
            /* JUST SOME STYLING HERE */

            // if (ieBug) {
            if (fpTableContainerDivElement.style.setExpression) {
                function fpIeBugFix(elementNode, containerNodeId, arrayOfExpressionsToSet) {
                    for (var i in arrayOfExpressionsToSet) {
                        if (arrayOfExpressionsToSet[i][2]) {
                            elementNode.style.setExpression(arrayOfExpressionsToSet[i][0], arrayOfExpressionsToSet[i][1]+"document.getElementById('"+containerNodeId+"')."+arrayOfExpressionsToSet[i][2]+"+'px'");
                        } else {
                            elementNode.style.setExpression(arrayOfExpressionsToSet[i][0], arrayOfExpressionsToSet[i][1]);
                        }
                    }
                }
                fpIeBugFix(fpTableContainerDivElement.copy3, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"],["marginTop","-","scrollTop"]]);
                fpIeBugFix(fpTableContainerDivElement.copy2, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"],["marginLeft","-","scrollLeft"]]);
                fpIeBugFix(fpTableContainerDivElement.copy1, fpTableContainerDivElementId, [["top","","scrollTop"],["left","","scrollLeft"]]);
                fpIeBugFix(fpTableContainerDivElement, fpTableContainerDivElementId, [["width","fpCW()+'px'"],["height","fpCH()+'px'"]]);
                document.recalc(true);
            } else {
                fpElement.onmousemove = fpElement.onscroll = function() {
                    if (!this.repositioning) {
                        this.repositioning = true;
                        var st = this.scrollTop;
                        var sl = this.scrollLeft;
                        if ((this.oldST != st) || (this.oldSL != sl)) {
                            this.oldST = st;
                            this.oldSL = sl;
                            // this.copy3.previousDisplay = this.copy3.style.display;
                            // this.copy3.style.display = "none";
                            this.copy3.style.marginTop = "-"+(st)+"px";
                            // this.copy3.style.display = this.copy3.previousDisplay;
                            // this.copy2.previousDisplay = this.copy2.style.display;
                            // this.copy2.style.display = "none";
                            this.copy2.style.marginLeft = "-"+(sl)+"px";
                            // this.copy2.style.display = this.copy2.previousDisplay;
                        }
                        fpElement.repositioning = false;
                    }
                };
                window.onresize = function() {
                    fpElement.style.width = fpCW()+"px";
                    fpElement.style.height = fpCH()+"px";
                }
            }
        }
    }
}

好的,根据上面的表,我已经有了,我必须假设固定列有固定的宽度,但我设法做到了

<div style="position:relative;">
    <div style="width:100%; overflow:scroll; height:400px;">

<table style="margin-left:100px;">
  <tr><td style="position:absolute;"></td><td colspan='31'>Jan</td><td colspan='28'>feb</td>...</tr>
  <tr><td style="position:absolute;"></td><td>1</td><td>2</td><td>3</td> ...<tr/>
  <tr><td style="position:absolute;">Person 1</td><td></td><td></td><td>Busy</td> ...<tr/>
  <tr><td style="position:absolute;">Person 2</td><td></td><td>Busy</td><td>Busy</td> ...<tr/>
</table>

    </div>
</div>

一月二日。。。
123 ...
人1Busy。。。
人2BusyBusy。。。
这将导致标记的单元格占据左侧的绝对位置,并且表格保持可滚动状态。。。 需要做一点工作来清理它,使它看起来漂亮,但基本上我的代码在提取出来时是这样的

<style type="text/css">
    .Calendar                   { max-height:400px; border-collapse:collapse; table-layout:fixed; margin-left:105px; }
    .Calendar .Resources  { width:100px; position:absolute; left:0px; background:white; }
    .Calendar tr                { vertical-align:top; }
    .Calendar td               { border:solid 1px black; vertical-align:top; padding:2px; border:solid 1px  #EFEFEF; }
    .Calendar .day            { background:#FFFBD6; border:solid 1px #FEEFB3; }
    .Calendar .dayWithEvent   { background:white; border:solid 1px #FEEFB3; border-top:solid 1px blue; }
</style>

<div style="position:relative;">
    <div style="width:100%; overflow:scroll; height:400px;">
        <table class="Calendar">
            <asp:Repeater ID="ui_calMonths" runat="server" onitemdatabound="ui_calMonths_ItemDataBound">
                    <HeaderTemplate>
                        <tr><td class="Resources" style="background:white; border:none;">&nbsp;</td>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <td colspan='<%# ((Month)Container.DataItem).Days.Length %>'><%# Eval("Name") %></td>
                    </ItemTemplate>
                    <FooterTemplate>
                        </tr>
                        <tr><td class="Resources" style="background:white; border:none;">&nbsp;</td>
                            <asp:Repeater ID="ui_calDays" runat="server">
                                <ItemTemplate>
                                    <td><%# ((DateTime)Container.DataItem).ToString("dd") %></td>
                                </ItemTemplate>
                            </asp:Repeater>
                        </tr>
                    </FooterTemplate>
                </asp:Repeater> 
            <asp:Repeater ID="ui_grdResources" runat="server">
                <HeaderTemplate><tr></HeaderTemplate>
                <ItemTemplate>
                    <td class="Resources"><%# Eval("Text") %></td>
                    <%# ResourceEvents(((RowContext)Container.DataItem)) %>
                </ItemTemplate>
                <FooterTemplate></tr></FooterTemplate>
            </asp:Repeater>
        </table>    
    </div>
</div>

.Calendar{最大高度:400px;边框折叠:折叠;表格布局:固定;左边距:105px;}
.Calendar.Resources{宽度:100px;位置:绝对;左侧:0px;背景:白色;}
.Calendar tr{垂直对齐:顶部;}
.Calendar td{边框:实心1px黑色;垂直对齐:顶部;填充:2px;边框:实心1px#EFEFEF;}
.Calendar.day{background:#FFFBD6;border:solid 1px#FEEFB3;}
.Calendar.dayWithEvent{背景:白色;边框:实心1px#FEEFB3;边框顶部:实心1px蓝色;}

基本上,codebehind计算出每行中要渲染的单元数(中继器是这项工作的基础,但结果基本上是一个格式良好的表格,第一行包含给定日期范围的月份名称,第二行和第三行包含这些月份的天数,一个固定列包含名称,并从我的内部API日历项动态填充…非常酷。)!!!

好的,根据上面的表格,我已经假设固定列的宽度是固定的,但是我成功地做到了

<div style="position:relative;">
    <div style="width:100%; overflow:scroll; height:400px;">

<table style="margin-left:100px;">
  <tr><td style="position:absolute;"></td><td colspan='31'>Jan</td><td colspan='28'>feb</td>...</tr>
  <tr><td style="position:absolute;"></td><td>1</td><td>2</td><td>3</td> ...<tr/>
  <tr><td style="position:absolute;">Person 1</td><td></td><td></td><td>Busy</td> ...<tr/>
  <tr><td style="position:absolute;">Person 2</td><td></td><td>Busy</td><td>Busy</td> ...<tr/>
</table>

    </div>
</div>

一月二日。。。
123 ...
人1Busy。。。
人2BusyBusy。。。
这将导致标记的单元格占据左侧的绝对位置,并且表格保持可滚动状态。。。 需要做一点工作来清理它,使它看起来漂亮,但基本上我的代码在提取出来时是这样的

<style type="text/css">
    .Calendar                   { max-height:400px; border-collapse:collapse; table-layout:fixed; margin-left:105px; }
    .Calendar .Resources  { width:100px; position:absolute; left:0px; background:white; }
    .Calendar tr                { vertical-align:top; }
    .Calendar td               { border:solid 1px black; vertical-align:top; padding:2px; border:solid 1px  #EFEFEF; }
    .Calendar .day            { background:#FFFBD6; border:solid 1px #FEEFB3; }
    .Calendar .dayWithEvent   { background:white; border:solid 1px #FEEFB3; border-top:solid 1px blue; }
</style>

<div style="position:relative;">
    <div style="width:100%; overflow:scroll; height:400px;">
        <table class="Calendar">
            <asp:Repeater ID="ui_calMonths" runat="server" onitemdatabound="ui_calMonths_ItemDataBound">
                    <HeaderTemplate>
                        <tr><td class="Resources" style="background:white; border:none;">&nbsp;</td>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <td colspan='<%# ((Month)Container.DataItem).Days.Length %>'><%# Eval("Name") %></td>
                    </ItemTemplate>
                    <FooterTemplate>
                        </tr>
                        <tr><td class="Resources" style="background:white; border:none;">&nbsp;</td>
                            <asp:Repeater ID="ui_calDays" runat="server">
                                <ItemTemplate>
                                    <td><%# ((DateTime)Container.DataItem).ToString("dd") %></td>
                                </ItemTemplate>
                            </asp:Repeater>
                        </tr>
                    </FooterTemplate>
                </asp:Repeater> 
            <asp:Repeater ID="ui_grdResources" runat="server">
                <HeaderTemplate><tr></HeaderTemplate>
                <ItemTemplate>
                    <td class="Resources"><%# Eval("Text") %></td>
                    <%# ResourceEvents(((RowContext)Container.DataItem)) %>
                </ItemTemplate>
                <FooterTemplate></tr></FooterTemplate>
            </asp:Repeater>
        </table>    
    </div>
</div>

.Calendar{最大高度:400px;边框折叠:折叠;表格布局:固定;左边距:105px;}
.Calendar.Resources{宽度:100px;位置:绝对;左侧:0px;背景:白色;}
.Calendar tr{垂直对齐:顶部;}
.Calendar td{边框:实心1px黑色;垂直对齐:顶部;填充:2px;边框:实心1px#EFEFEF;}
.Calendar.day{background:#FFFBD6;border:solid 1px#FEEFB3;}
.Calendar.dayWithEvent{背景:白色;边框:实心1px#FEEFB3;边框顶部:实心1px蓝色;}

基本上,codebehind计算出每行中要渲染的单元数(中继器是这项工作的基础,但结果基本上是一个格式良好的表格,第一行包含给定日期范围的月份名称,第二行和第三行包含这些月份的天数,一个固定列包含名称,并从我的内部API日历项动态填充…非常酷。)!!!

获取jquery datatables fixedcolumns插件

获取jquery