2009-07-01 6 views
2

J'ai réécrit le DataGridRow dans le DataGrid Microsoft WPF à ci-dessous, le problème que je rencontre est que si l'utilisateur clique sur les éléments de bordure du modèle la ou les lignes ne pas être sélectionné. Y at-il un moyen de faire le clic sur la bordure provoquer une sélection de ligne.Bordure dans ControlTemplate provoquant un comportement de sélection impaire avec 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> 

Répondre

2

L'appel d'une méthode interne semble quelque peu dangereux. Et si les détails de la mise en œuvre changent? Il y a eu beaucoup de changements dans les versions précédentes.

je pense qu'il peut être plus prudent de simplement ajouter un gestionnaire d'événements comme celui-ci à vos lignes:

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); 
    } 
} 

Cela aurait le même effet que de cliquer sur la cellule elle-même, et utiliserait uniquement les membres du public de Éléments DataGrid.

+0

Fonctionne très bien, merci! – dariusriggins

1

La boîte à outils DataGridRow n'a pas défini de substitution OnMouseDown ou méthode similaire. La sélection d'un creux est traitée rangée complète de cette méthode:

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(); 
    } 
} 

Cette méthode est appelée lorsque l'entrée se produit sur une cellule . La méthode MakeFullRowSelection sélectionne uniquement toutes les cellules d'une ligne, pas la ligne elle-même. Par conséquent, lorsque vous cliquez sur un DataGridRow (et non un DataGridCell), aucune gestion de la souris ou de la sélection ne se produit. Pour accomplir ce que vous désirez, vous devez ajouter une sorte de gestionnaire de souris vers le bas aux événements de souris à la baisse de vos lignes où vous définiriez la propriété IsSelected. Bien sûr, notez que vous devez spécifier la propriété sélectionnée pour chaque cellule de la ligne individuellement, car la ligne row.IsSelected n'implique pas ou ne définit pas cette propriété.

0

Merci pour la réponse, j'ai eu l'idée générale, mais en réglant le IsSelected sur true n'a pas fonctionné comme je l'espérais, quand ce coup cela ferait que la ligne soit sélectionnée mais pas désélectionner l'autre rangée (dans le cas, il devrait avoir). J'ai été capable de contourner le problème en appelant le HandleSelectionForCellInput dans mon gestionnaire. Ensuite, je viens d'appeler le Lambda créé par le bas avec la grille et la cellule, fonctionne parfaitement.

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(); 
}