2012-12-08 13 views
7

グリッド(DataGridではなく)に基づいて、ScrollViewerでラップされたユーザーコントロールを作成しました。今私はDataGridのように行/列の機能を固定したいと思いますが、方法を理解することはできませんでした。WPF DataGridはフリーズした行/列をどのように動作させますか?

誰かがWPF DataGridでどのように行われているか、いくつかの洞察を教えてくれますか?あなたは私はあなたが以下の

を行うのどちらか選択した行または列のイベントで、その後にそれを望むお勧めの列をフリーズする場合

+1

凍結とはどういう意味ですか?サイズ? – Joe

+0

DataGridやExcelなどのフリーズされた行/列。ヘッダーは常に表示されます。具体的には、上部の列見出しは水平方向にスクロールできますが、垂直方向にはスクロールできません。左側の行ヘッダーは垂直方向にスクロールできますが、水平方向にはスクロールできません。 – newman

答えて

0

DataGrid列と行は、「フローズン」

と呼ばれる性質を持っていますイベントには、列/行を取得し、真の冷凍=

としてそれをマークするか、別のボタンまたはマウスのコンテキストメニューを作成し、右あなたが現在マーク

列/行をアンフリーズ/フリーズれているクリック

は自分でこの問題が発生した後、私は私がこれまでに出て見つけたものを共有したい、これは

+0

これは問題が他のものであるために役立ちません。 – Ramin

+0

あなたのご意見ありがとうございます、Sagar、それは私が尋ねたものではありません。 – newman

4

に役立ちます願っています。

DataGridは、2つの異なる方法を使用しています。


まず:行ヘッダ


これは単純化されたTemplateDataGridRowためのものです:

<Border x:Name="DGR_Border" ... > 
    <SelectiveScrollingGrid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 

     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 

     <DataGridRowHeader Grid.RowSpan="2" 
      SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" ... /> 

     <DataGridCellsPresenter Grid.Column="1" ... /> 

     <DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" 
      SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, 
                      Path=AreRowDetailsFrozen, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, 
                      ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}" ... /> 
    </SelectiveScrollingGrid> 
</Border> 

あなたがDataGridを見ることができるようにして行ヘッダを保持するためにSelectiveScrollingOrientation添付プロパティを使用していますポジション。このプロパティが設定されている(または変更されている)場合、親にバインドされたTranslateTransformが作成されます。ScrollViewer要素のオフセット。詳細はsource codeを参照してください。


第二:FrozenColumns


このようなものはDataGridCellsPanelArrangeOverride()で行われます。これは、プライベートArrangeStateクラスを使用して、 "複数の子のアレンジの間の状態を維持する"。

private class ArrangeState 
{ 
    public ArrangeState() 
    { 
     FrozenColumnCount = 0; 
     ChildHeight = 0.0; 
     NextFrozenCellStart = 0.0; 
     NextNonFrozenCellStart = 0.0; 
     ViewportStartX = 0.0; 
     DataGridHorizontalScrollStartX = 0.0; 
     OldClippedChild = null; 
     NewClippedChild = null; 
    } 

    public int FrozenColumnCount { get; set; } 
    public double ChildHeight { get; set; } 
    public double NextFrozenCellStart { get; set; } 
    public double NextNonFrozenCellStart { get; set; } 
    public double ViewportStartX { get; set; } 
    public double DataGridHorizontalScrollStartX { get; set; } 
    public UIElement OldClippedChild { get; set; } 
    public UIElement NewClippedChild { get; set; } 
} 

private void InitializeArrangeState(ArrangeState arrangeState) 
{ 
    DataGrid parentDataGrid = ParentDataGrid; 
    double horizontalOffset = parentDataGrid.HorizontalScrollOffset; 
    double cellsPanelOffset = parentDataGrid.CellsPanelHorizontalOffset; 
    arrangeState.NextFrozenCellStart = horizontalOffset; 
    arrangeState.NextNonFrozenCellStart -= cellsPanelOffset; 
    arrangeState.ViewportStartX = horizontalOffset - cellsPanelOffset; 
    arrangeState.FrozenColumnCount = parentDataGrid.FrozenColumnCount; 
} 

た状態を初期化した後、それは、すべての実現チャイルズため

ArrangeChild(children[childIndex] as UIElement, i, arrangeState); 

を呼び出し、非実現チャイルズ/列の推定幅を算出します。

double childSize = GetColumnEstimatedMeasureWidth(column, averageColumnWidth); 
arrangeState.NextNonFrozenCellStart += childSize; 

端における値はDataGridの適切なフィールドに設定されます。

private void FinishArrange(ArrangeState arrangeState) 
{ 
    DataGrid parentDataGrid = ParentDataGrid; 

    // Update the NonFrozenColumnsViewportHorizontalOffset property of datagrid 
    if (parentDataGrid != null) 
    { 
     parentDataGrid.NonFrozenColumnsViewportHorizontalOffset = arrangeState.DataGridHorizontalScrollStartX; 
    } 

    // Remove the clip on previous clipped child 
    if (arrangeState.OldClippedChild != null) 
    { 
     arrangeState.OldClippedChild.CoerceValue(ClipProperty); 
    } 

    // Add the clip on new child to be clipped for the sake of frozen columns. 
    _clippedChildForFrozenBehaviour = arrangeState.NewClippedChild; 
    if (_clippedChildForFrozenBehaviour != null) 
    { 
     _clippedChildForFrozenBehaviour.CoerceValue(ClipProperty); 
    } 
} 

あなたはsource codeにライン1470から見つけることができますArrangeChild(UIElement child, int displayIndex, ArrangeState arrangeState)の詳細。それは作るの列が凍結されているように単純ではありません


結論


。これは、(離れて全幅にわたってクリッピングやスクロールバーから)

<ListView ItemsSource="some rows"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <TextBlock Grid.Column="0" Text="Fixed" 
          Background="LightBlue" Width="300" 
          SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" /> 
       <TextBlock Grid.Column="1" Text="Scrolled" 
          Background="LightGreen" Width="300" /> 
      </Grid> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

に動作しますにもかかわらず、これはしません。

<ScrollViewer HorizontalScrollBarVisibility="Auto"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 
     <TextBlock Grid.Column="0" Text="Fixed" 
        Background="LightBlue" Width="300" 
        SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" /> 
     <TextBlock Grid.Column="1" Text="Scrolled" 
        Background="LightGreen" Width="300" />      
    </Grid> 
</ScrollViewer> 

理由はSelectiveScrollingOrientation attached propertyDataGridHelper.FindVisualParent<ScrollViewer>(element)は(souce codeにライン149から参照)が失敗したということです。あなたは回避策を見つけるかもしれません。元のコードのコピーを使用して独自の添付プロパティを作成しますが、名前はScrollViewerになります。それ以外の場合は、最初から多くのことをしなければならないと思います。

+0

さて、私はそこにいくつかの手掛かりを見るが、私はそれが私のために働くことができませんでした。もう少しヒントを与えてもらえますか? – newman

+0

同じ問題が発生した後、私の更新された回答をご覧ください。 – LPL

関連する問題