2009-07-01 99 views
2

我已經在Microsoft WPF DataGrid中將DataGridRow重新定位到下面,我遇到的問題是如果用戶單擊Row(s)模板的邊框元素,不要選擇。有沒有辦法讓點擊邊框導致行選擇。ControlTemplate中的邊框導致DataGrid奇怪的選擇行爲

<Grid x:Name="LayoutRoot" Margin="0,0,0,-1"> 
     <Border x:Name="DGR_Border" BorderBrush="Transparent" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True"> 
      <Border x:Name="DGR_InnerBorder" BorderBrush="Transparent" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True"> 
       <toolkit:SelectiveScrollingGrid Name="DGR_SelectiveScrollingGrid"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 

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

        <toolkit:DataGridCellsPresenter Grid.Column="1" Name="DGR_CellsPresenter" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
        <toolkit:DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" Visibility="{TemplateBinding DetailsVisibility}" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static Controls:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static Controls:SelectiveScrollingOrientation.Vertical}}" /> 
        <toolkit:DataGridRowHeader Grid.RowSpan="2" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}, Path=HeadersVisibility, Converter={x:Static Controls:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static Controls:DataGridHeadersVisibility.Row}}"/> 
       </toolkit:SelectiveScrollingGrid> 
      </Border> 
     </Border> 
    </Grid> 

回答

2

調用內部方法似乎有點危險。如果實施細節發生變化呢?以前的版本有很多變化。

我認爲它可能是更謹慎的做法簡單地添加事件處理這樣您行:

protected void DataGridRow_MouseDown(object sender, MouseButtonEventArgs e) 
{ 
    // GetVisualChild<T> helper method, simple to implement 
    DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); 

    // try to get the first cell in a row 
    DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(0); 
    if (cell != null) 
    { 
     RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseLeftButtonDownEvent); 
     //if the DataGridSelectionUnit is set to FullRow this will have the desired effect 
     cell.RaiseEvent(newEventArgs); 
    } 
} 

這將具有與單擊該單元格本身相同的效果,並且將只使用的公共成員DataGrid元素。

+0

很好,謝謝! – dariusriggins 2009-07-08 13:04:24

1

工具包DataGridRow沒有定義的OnMouseDown覆蓋或類似的方法。一個完整的行的選擇的處理槽此方法:當輸入上的細胞發生

internal void HandleSelectionForCellInput(DataGridCell cell, bool startDragging, bool allowsExtendSelect, bool allowsMinimalSelect) 
{ 
    DataGridSelectionUnit selectionUnit = SelectionUnit; 

    // If the mode is None, then no selection will occur 
    if (selectionUnit == DataGridSelectionUnit.FullRow) 
    { 
     // In FullRow mode, items are selected 
     MakeFullRowSelection(cell.RowDataItem, allowsExtendSelect, allowsMinimalSelect); 
    } 
    else 
    { 
     // In the other modes, cells can be individually selected 
     MakeCellSelection(new DataGridCellInfo(cell), allowsExtendSelect, allowsMinimalSelect); 
    } 

    if (startDragging) 
    { 
     BeginDragging(); 
    } 
} 

此方法被調用。 MakeFullRowSelection方法只選擇一行中的所有單元格,而不是行本身。

因此,當您單擊DataGridRow(而不是DataGridCell)時,不會發生鼠標停頓或選擇處理。爲了實現你的願望,你應該添加一些鼠標放下處理程序到你設置IsSelected屬性的行的鼠標放下事件。當然,請注意,您應該爲行中的每個單元格單獨指定所選屬性,因爲row.IsSelected不會暗示或設置該屬性。

0

感謝您的迴應,我得到了一般想法,但是將IsSelected設置爲true並不按照我預期的方式工作,當它打到時會導致該行被選中,但不會取消選擇另一行(在它應該有的情況)。我能夠通過在我的處理程序中調用HandleSelectionForCellInput來解決問題。然後我只需調用從網格和單元格下面創建的Lambda,完美地工作。

public static Action<DataGrid, DataGridCell, bool> CreateSelectRowMethod(bool allowExtendSelect, bool allowMinimalSelect) 
{ 
var selectCellMethod = typeof(DataGrid).GetMethod("HandleSelectionForCellInput", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 

ParameterExpression dataGrid = Expression.Parameter(typeof(DataGrid), "dataGrid"); 
ParameterExpression paramCell = Expression.Parameter(typeof(DataGridCell), "cell"); 
ParameterExpression paramStartDragging = Expression.Parameter(typeof(bool), "startDragging"); 
var paramAllowsExtendSelect = Expression.Constant(allowExtendSelect, typeof(bool)); 
var paramAllowsMinimalSelect = Expression.Constant(allowMinimalSelect, typeof(bool)); 

var call = Expression.Call(dataGrid, selectCellMethod, paramCell, paramStartDragging, paramAllowsExtendSelect, paramAllowsMinimalSelect); 

return (Action<DataGrid, DataGridCell, bool>)Expression.Lambda(call, dataGrid, paramCell, paramStartDragging).Compile(); 
}