.NET Framework-3.5の最新バージョンは、多くの改善と新機能をもたらしました。その1つは、ListViewとDataPagerの「甘いカップル」です。
ある時点で、ページ間でDataPagerナビゲーションを使用して実装したいと考えていました。たとえば、HabréやLeprosyで行われているように、数値が大きくなり、小さくなります。 この順序は、たとえば、日付-最初の新しい順にソートされたリストを表示するのに最適です。 通常のカウントは、NumericPagerFieldフィールドを使用して基本的に実装されますが、このコントロールには参照方向を変更するメソッドは含まれません。
グーグルは提起された質問に既製の答えを与えなかったので、TemplatePagerFieldを使用して完全に混乱するか、完成したNumericPagerFieldを何らかの方法で変更するかを選択しました。 私は2番目の方法がより好きで、それに沿って行きました。
最初はNumericPagerFieldのCreateDataPagerメソッドを書き直したかったのですが、不可能だったため、NumericPagerFieldの基本クラスであるDataPagerFieldを継承し、独自のページャーを作成する必要がありました。 そうすることで、私は.NET Framework 3.5のソースコードを利用しました。
そこで、逆ページャーを作成します。 これを行うには、DataPagerFieldを継承して、新しいReversedNumericPagerFieldクラスを作成します。
パブリック クラス ReversedNumericPagerField:DataPagerField 
{ 
private int _startRowIndex; 
private int _maximumRows; 
private int _totalRowCount; 
public ReversedNumericPagerField() 
{ 
} 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
新しいページャーが何らかの形で機能するためには、CreatePage、CreateDataPagers、HandleEventの各メソッドを実装する必要があります。 いくつかのグローバル変数も必要です。_startRowIndex-最初に表示されるリストアイテムのインデックス、_maximumRows-1ページに表示されるリストアイテムの数、_totalRowCount-リスト内のアイテムの数。
CreateFieldメソッド。
これですべてがシンプルになります-ReversedNumericPagerFieldクラスのインスタンスを返します。
保護された オーバーライド DataPagerField CreateField() 
{ 
新しい ReversedNumericPagerField()を返します。 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
CreateDataPagersメソッド。
このメソッドが必要です。ページに何をいつ表示するかを決定し、必要なコントロールを作成します。
パブリック オーバーライド void CreateDataPagers(DataPagerFieldItemコンテナー、 int startRowIndex、 int maximumRows、 int totalRowCount、 int fieldIndex) 
{ 
_startRowIndex = startRowIndex; 
_maximumRows = maximumRows; 
_totalRowCount = totalRowCount; 
CreateDataPagersForCommand(コンテナ、fieldIndex); 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
元のNumericPagerFieldは、ページを使用して、QueryStringsを使用して、通常のページリンクとLinkButtonなどのボタンの両方を生成できることに注意してください。 必要なのは2番目だけですが、両方のケースが必要な場合は、このコントロール(コントロール)のプロパティに応じて、異なる機能で実装し、適切なケースを選択するのが最善です。 この場合、LinkButtonの機能はCreateDataPagersForCommand関数によって実装されます。この関数は、「単純な」数学的変換により、ボタンに描画する図形の種類を決定し、このボタンを作成します。
private void CreateDataPagersForCommand(DataPagerFieldItemコンテナー、 int fieldIndex) 
{ 
int currentPageIndex = _startRowIndex / _maximumRows; 
int firstButtonIndex =(_startRowIndex /(ButtonCount * _maximumRows))* ButtonCount; 
int lastButtonIndex = firstButtonIndex + ButtonCount-1; 
int lastRecordIndex =((lastButtonIndex + 1)* _maximumRows)-1; 
int totalPages =( int ) Math .Ceiling(( double )_totalRowCount / _maximumRows); 
for ( int i = 0; i <ButtonCount && _totalRowCount>((i + firstButtonIndex)* _maximumRows); i ++) 
{ 
if (i + firstButtonIndex == currentPageIndex) 
{ 
ラベルpageNumber = 新しいラベル(); 
pageNumber.Text =(totalPages-i-firstButtonIndex).ToString(); 
container.Controls.Add(pageNumber); 
} 
他に 
{ 
container.Controls.Add(CreateNumericButton((totalPages-i-firstButtonIndex).ToString()、fieldIndex.ToString()、(i + firstButtonIndex).ToString())); 
} 
container.Controls.Add( new LiteralControl( "" )); 
} 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
ここで、ボタンを作成するために、次の関数が呼び出されます。実際には、指定されたプロパティを持つLinkButtonのインスタンスを返します。
プライベートコントロールCreateNumericButton( string buttonText、 string commandArgument、 string commandName) 
{ 
LinkButton button = new LinkButton(); 
button.Text = buttonText; 
button.CommandName = commandName; 
button.CommandArgument = commandArgument; 
コントロールとして 戻るボタン。 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
HandleEventメソッド
このメソッドはページャーでイベントを処理し、ほとんど変更なしで継承されたクラスから取得されました。
パブリック オーバーライド void HandleEvent(CommandEventArgs e) 
{ 
int newStartRowIndex = -1; 
int currentPageIndex = _startRowIndex / DataPager.PageSize; 
int firstButtonIndex =(_startRowIndex /(ButtonCount * DataPager.PageSize))* ButtonCount; 
int lastButtonIndex = firstButtonIndex + ButtonCount-1; 
int lastRecordIndex =((lastButtonIndex + 1)* DataPager.PageSize)-1; 
if ( String .Equals(e.CommandName、DataControlCommands.PreviousPageCommandArgument)) 
{ 
newStartRowIndex =(firstButtonIndex-1)* DataPager.PageSize; 
if (newStartRowIndex <0) 
{ 
newStartRowIndex = 0; 
} 
} 
else if ( String .Equals(e.CommandName、DataControlCommands.NextPageCommandArgument)) 
{ 
newStartRowIndex = lastRecordIndex + 1; 
if (newStartRowIndex> _totalRowCount) 
{ 
newStartRowIndex = _totalRowCount-DataPager.PageSize; 
} 
} 
他に 
{ 
int pageIndex = Convert .ToInt32(e.CommandName、CultureInfo.InvariantCulture); 
newStartRowIndex = pageIndex * DataPager.PageSize; 
} 
if (newStartRowIndex!= -1) 
{ 
DataPager.SetPageProperties(newStartRowIndex、DataPager.PageSize、 true ); 
} 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
これは基本的にすべてで、受信したページャーは目的の順序で番号を表示しますが、実際には裸であるため非常にいです-CSSクラスを指定するプロパティがなく、前のページと次のページのリンクを作成しません、など しかし、これがどのように機能するかがより明確になることを願っています。 次のコードは、すべての補助機能とプロパティを備えたページャーを完全に表しています。
パブリック クラス ReversedNumericPagerField:DataPagerField 
{ 
private int _startRowIndex; 
private int _maximumRows; 
private int _totalRowCount; 
public ReversedNumericPagerField() 
{ 
} 
public int ButtonCount 
{ 
得る 
{ 
オブジェクト o = ViewState [ "ButtonCount" ]; 
if (o!= null ) 
{ 
return ( int )o; 
} 
return 5; 
} 
セット 
{ 
if ( 値 <1) 
{ 
新しい ArgumentOutOfRangeException( "value" );をスローします。 
} 
if ( value != ButtonCount) 
{ 
ViewState [ "ButtonCount" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
public ButtonType ButtonType 
{ 
得る 
{ 
オブジェクト o = ViewState [ "ButtonType" ]; 
if (o!= null ) 
return (ButtonType)o; 
return ButtonType.Link; 
} 
セット 
{ 
if ( value <ButtonType.Button || value > ButtonType.Link) 
{ 
新しい ArgumentOutOfRangeException( "value" );をスローします。 
} 
if ( value != ButtonType) 
{ 
ViewState [ "ButtonType" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 CurrentPageLabelCssClass 
{ 
得る 
{ 
オブジェクト o = ViewState [ "CurrentPageLabelCssClass" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return String .Empty; 
} 
セット 
{ 
if ( value != CurrentPageLabelCssClass) 
{ 
ViewState [ "CurrentPageLabelCssClass" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 NextPageImageUrl 
{ 
得る 
{ 
オブジェクト o = ViewState [ "NextPageImageUrl" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return String .Empty; 
} 
セット 
{ 
if ( value != NextPageImageUrl) 
{ 
ViewState [ "NextPageImageUrl" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 NextPageText 
{ 
得る 
{ 
オブジェクト o = ViewState [ "NextPageText" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
「→」を 返します。 
} 
セット 
{ 
if ( value != NextPageText) 
{ 
ViewState [ "NextPageText" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 NextPreviousButtonCssClass 
{ 
得る 
{ 
オブジェクト o = ViewState [ "NextPreviousButtonCssClass" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return String .Empty; 
} 
セット 
{ 
if ( value != NextPreviousButtonCssClass) 
{ 
ViewState [ "NextPreviousButtonCssClass" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 NumericButtonCssClass 
{ 
得る 
{ 
オブジェクト o = ViewState [ "NumericButtonCssClass" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return String .Empty; 
} 
セット 
{ 
if ( value != NumericButtonCssClass) 
{ 
ViewState [ "NumericButtonCssClass" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 PreviousPageImageUrl 
{ 
得る 
{ 
オブジェクト o = ViewState [ "PreviousPageImageUrl" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return String .Empty; 
} 
セット 
{ 
if ( value != PreviousPageImageUrl) 
{ 
ViewState [ "PreviousPageImageUrl" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック 文字列 PreviousPageText 
{ 
得る 
{ 
オブジェクト o = ViewState [ "PreviousPageText" ]; 
if (o!= null ) 
{ 
return ( string )o; 
} 
return "←" ; 
} 
セット 
{ 
if ( value != PreviousPageText) 
{ 
ViewState [ "PreviousPageText" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
パブリック bool RenderNonBreakingSpacesBetweenControls 
{ 
得る 
{ 
オブジェクト o = ViewState [ "RenderNonBreakingSpacesBetweenControls" ]; 
if (o!= null ) 
{ 
return ( bool )o; 
} 
trueを 返し ます 。 
} 
セット 
{ 
if ( value != RenderNonBreakingSpacesBetweenControls) 
{ 
ViewState [ "RenderNonBreakingSpacesBetweenControls" ] = value ; 
OnFieldChanged(); 
} 
} 
} 
プライベート void AddNonBreakingSpace(DataPagerFieldItemコンテナー) 
{ 
if (RenderNonBreakingSpacesBetweenControls) 
{ 
container.Controls.Add( new LiteralControl( "" )); 
} 
} 
保護された オーバーライド DataPagerField CreateField() 
{ 
新しい ReversedNumericPagerField()を返します。 
} 
パブリック オーバーライド void HandleEvent(CommandEventArgs e) 
{ 
int newStartRowIndex = -1; 
int currentPageIndex = _startRowIndex / DataPager.PageSize; 
int firstButtonIndex =(_startRowIndex /(ButtonCount * DataPager.PageSize))* ButtonCount; 
int lastButtonIndex = firstButtonIndex + ButtonCount-1; 
int lastRecordIndex =((lastButtonIndex + 1)* DataPager.PageSize)-1; 
if ( String .Equals(e.CommandName、DataControlCommands.PreviousPageCommandArgument)) 
{ 
newStartRowIndex =(firstButtonIndex-1)* DataPager.PageSize; 
if (newStartRowIndex <0) 
{ 
newStartRowIndex = 0; 
} 
} 
else if ( String .Equals(e.CommandName、DataControlCommands.NextPageCommandArgument)) 
{ 
newStartRowIndex = lastRecordIndex + 1; 
if (newStartRowIndex> _totalRowCount) 
{ 
newStartRowIndex = _totalRowCount-DataPager.PageSize; 
} 
} 
他に 
{ 
int pageIndex = Convert .ToInt32(e.CommandName、CultureInfo.InvariantCulture); 
newStartRowIndex = pageIndex * DataPager.PageSize; 
} 
if (newStartRowIndex!= -1) 
{ 
DataPager.SetPageProperties(newStartRowIndex、DataPager.PageSize、 true ); 
} 
} 
プライベートコントロールCreateNumericButton( string buttonText、 string commandArgument、 string commandName) 
{ 
IButtonControlボタン。 
スイッチ (ButtonType) 
{ 
case ButtonType.Button: 
button = 新しいボタン(); 
休憩 ; 
case ButtonType.Link: 
デフォルト : 
button = new LinkButton(); 
休憩 ; 
} 
button.Text = buttonText; 
button.CommandName = commandName; 
button.CommandArgument = commandArgument; 
WebControl webControl = button as WebControl; 
if (webControl!= null &&! String .IsNullOrEmpty(NumericButtonCssClass)) 
{ 
webControl.CssClass = NumericButtonCssClass; 
} 
コントロールとして 戻るボタン。 
} 
プライベートコントロールCreateNextPrevButton( string buttonText、 string commandName、 string commandArgument、 string imageUrl) 
{ 
IButtonControlボタン。 
スイッチ (ButtonType) 
{ 
case ButtonType.Link: 
button = new LinkButton(); 
休憩 ; 
case ButtonType.Button: 
button = 新しいボタン(); 
休憩 ; 
case ButtonType.Image: 
デフォルト : 
button = new ImageButton(); 
((ImageButton)ボタン).ImageUrl = imageUrl; 
((ImageButton)ボタン).AlternateText = HttpUtility.HtmlDecode(buttonText); 
休憩 ; 
} 
button.Text = buttonText; 
button.CommandName = commandName; 
button.CommandArgument = commandArgument; 
WebControl webControl = button as WebControl; 
if (webControl!= null &&! String .IsNullOrEmpty(NextPreviousButtonCssClass)) 
{ 
webControl.CssClass = NextPreviousButtonCssClass; 
} 
コントロールとして 戻るボタン。 
} 
パブリック オーバーライド void CreateDataPagers(DataPagerFieldItemコンテナー、 int startRowIndex、 int maximumRows、 int totalRowCount、 int fieldIndex) 
{ 
_startRowIndex = startRowIndex; 
_maximumRows = maximumRows; 
_totalRowCount = totalRowCount; 
CreateDataPagersForCommand(コンテナ、fieldIndex); 
} 
private void CreateDataPagersForCommand(DataPagerFieldItemコンテナー、 int fieldIndex) 
{ 
int currentPageIndex = _startRowIndex / _maximumRows; 
int firstButtonIndex =(_startRowIndex /(ButtonCount * _maximumRows))* ButtonCount; 
int lastButtonIndex = firstButtonIndex + ButtonCount-1; 
int lastRecordIndex =((lastButtonIndex + 1)* _maximumRows)-1; 
int totalPages =( int ) Math .Ceiling(( double )_totalRowCount / _maximumRows); 
if (firstButtonIndex!= 0) 
{ 
container.Controls.Add(CreateNextPrevButton(PreviousPageText、DataControlCommands.PreviousPageCommandArgument、fieldIndex.ToString(CultureInfo.InvariantCulture)、PreviousPageImageUrl)); 
AddNonBreakingSpace(コンテナー); 
} 
for ( int i = 0; i <ButtonCount && _totalRowCount>((i + firstButtonIndex)* _maximumRows); i ++) 
{ 
if (i + firstButtonIndex == currentPageIndex) 
{ 
ラベルpageNumber = 新しいラベル(); 
pageNumber.Text =(totalPages-i-firstButtonIndex).ToString(CultureInfo.InvariantCulture); 
if (! String .IsNullOrEmpty(CurrentPageLabelCssClass)) 
{ 
pageNumber.CssClass = CurrentPageLabelCssClass; 
} 
container.Controls.Add(pageNumber); 
} 
他に 
{ 
container.Controls.Add(CreateNumericButton((totalPages-i-firstButtonIndex).ToString(CultureInfo.InvariantCulture)、fieldIndex.ToString(CultureInfo.InvariantCulture)、(i + firstButtonIndex).ToString(CultureInfoult.Invant); 
} 
AddNonBreakingSpace(コンテナー); 
} 
if (lastRecordIndex <_totalRowCount-1) 
{ 
AddNonBreakingSpace(コンテナー); 
container.Controls.Add(CreateNextPrevButton(NextPageText、DataControlCommands.NextPageCommandArgument、fieldIndex.ToString(CultureInfo.InvariantCulture)、NextPageImageUrl)); 
AddNonBreakingSpace(コンテナー); 
} 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
このクラスは、その上に置かれた機能を実行し、逆の順序で数字を表示します。 ただし、それはホイップアップされており、おそらくCreateDataPagersForCommand関数の数学は完全に最適ではありません。 いずれにせよ、この記事が誰かの役に立つことを願っています。
その他。 これはプログラミングに関する最初の記事であり、それに応じてHabréの最初の記事であるため、日常の練習で英語を使用しているため、正しいロシアのプログラマー用語を選択することは容易ではありませんでした。 コメントを書いて、訂正します。 そして、プログラマーの英語-ロシア語辞書をアドバイスしてください:)