Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datagrid: MultiSelect | ShiftClick Feature #2151

Merged
merged 26 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1923db4
Update releases.md
stsrki Mar 5, 2021
f50458f
Update SUPPORTERS.md
stsrki Mar 9, 2021
35a986b
Remove dotnet.myget sources
stsrki Mar 9, 2021
1f00263
Add Static Files to DataGrid docs
stsrki Mar 11, 2021
f115cd6
Add Static Files section to RTE docs
stsrki Mar 11, 2021
9cbbdbf
Update richtextedit.md
stsrki Mar 11, 2021
25c3899
Update datagrid.md
stsrki Mar 11, 2021
2817bb1
Update SUPPORTERS.md
stsrki Mar 16, 2021
c706092
0.9.3.1 release notes
stsrki Mar 17, 2021
0db1b26
0.9.3.2 release notes
stsrki Mar 22, 2021
6fae916
0.9.3.3 release notes
stsrki Mar 26, 2021
78cb621
Update SUPPORTERS.md
stsrki Mar 26, 2021
aa3b8e7
Update SUPPORTERS.md
stsrki Mar 27, 2021
6cb62b0
Datagrid: MultiSelect | ShiftClick Feature
David-Moreira Apr 2, 2021
c75ab18
Merge branch 'dev094' into dev094-datagrid-multiselect-shiftClickFeature
stsrki Apr 6, 2021
b8d1584
Small optimizations
stsrki Apr 6, 2021
df54611
0.9.3.4 release notes
stsrki Apr 7, 2021
2f6ed83
Merge branch 'dev094-datagrid-multiselect-shiftClickFeature' of https…
David-Moreira Apr 7, 2021
83a6850
Method name fix
David-Moreira Apr 7, 2021
f98090f
Checked State Fix | It now only looks at Row Selected State instead o…
David-Moreira Apr 7, 2021
6736f7d
Merge branch 'dev094' into dev094-datagrid-multiselect-shiftClickFeature
stsrki Apr 9, 2021
596f8f6
Merge branch 'dev094' into dev094-datagrid-multiselect-shiftClickFeature
stsrki Apr 14, 2021
f0699b7
Able to handle constant row click
David-Moreira Apr 14, 2021
6890fec
Do not unselect SelectedRow when shift clicking an already multiselec…
David-Moreira Apr 14, 2021
fe93562
Merge branch 'dev094' into dev094-datagrid-multiselect-shiftClickFeature
stsrki Apr 15, 2021
1b99228
Fomating
stsrki Apr 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions Demos/Blazorise.Demo/Pages/Tests/DataGridPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,7 @@
</Button>
</FilterTemplate>
<MultiSelectTemplate>
<Label @onclick:stopPropagation>
<Check TValue="bool" Checked="@context.IsSelected" Indeterminate="@context.IsIndeterminate" CheckedChanged="@context.SelectedChanged" @onclick:stopPropagation></Check>
</Label>
<Check TValue="bool" Checked="@context.IsSelected" CheckedExpression="() => context.IsSelected" Indeterminate="@context.IsIndeterminate" CheckedChanged="@context.SelectedChanged"></Check>
</MultiSelectTemplate>
</DataGridMultiSelectColumn>
<DataGridCommandColumn TItem="Employee" Width="170px">
Expand Down Expand Up @@ -289,9 +287,6 @@
<SelectItem TValue="string" Value="@("D")">Diverse</SelectItem>
</Select>
</FilterTemplate>
@code{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What the hell was this doing here? Did I merge this in? xDD

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be accidentally merged from my own testings. I tend to throw it randomly like that but this time it slipped unnoticed.


}
<DisplayTemplate>
@{
var gender = ( context as Employee )?.Gender;
Expand Down
5 changes: 5 additions & 0 deletions SUPPORTERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,9 @@ In case you don't want to be on the list please let me know. And 'm sorry if I f
- Jesse Hamilton
- Logan Payton
- Catrina Zapata
- Angel Ruben
- TridentShoxx Labs
- Dejan Demonjić
- Sebastian Gerner
- Philip Näf
- Your name can be here, [become a patron](https://www.patreon.com/mladenmacanovic) or [buy me a coffee](https://www.buymeacoffee.com/mladenmacanovic)
3 changes: 2 additions & 1 deletion Source/Blazorise/Components/Table/TableRow.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ protected async Task OnClickHandler( MouseEventArgs eventArgs )
{
// https://stackoverflow.com/questions/5497073/how-to-differentiate-single-click-event-and-double-click-event
// works good enough. Click is still called before the double click, but it is advise to not use both events anyway.
if ( eventArgs.Detail == 1 )
// We'll be treating any Detail higher then 2 as the user constantly clicking, therefore triggering Single Click.
if ( eventArgs.Detail == 1 || eventArgs.Detail > 2 )
await Clicked.InvokeAsync( EventArgsMapper.ToMouseEventArgs( eventArgs ) );
else if ( eventArgs.Detail == 2 )
await DoubleClicked.InvokeAsync( EventArgsMapper.ToMouseEventArgs( eventArgs ) );
Expand Down
70 changes: 60 additions & 10 deletions Source/Extensions/Blazorise.DataGrid/DataGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ public partial class DataGrid<TItem> : BaseDataGridComponent
/// </summary>
protected PaginationContext<TItem> paginationContext;

/// <summary>
/// Holds the last known selected row index.
/// </summary>
protected internal short lastSelectedRowIndex;

#endregion

#region Constructors
Expand Down Expand Up @@ -392,32 +397,77 @@ protected void OnCancelCommand()
PopupVisible = false;
}

protected internal short ResolveItemIndex( TItem item )
{
short index = 0;
foreach ( var displayItem in DisplayData )
{
if ( item.IsEqual( displayItem ) )
break;
index++;
}
return index;
}

protected async Task OnMultiSelectCommand( MultiSelectEventArgs<TItem> eventArgs )
{
SelectedAllRows = false;
UnSelectAllRows = false;

if ( SelectedRows is null )
{
SelectedRows = new List<TItem>();
}
SelectedRows ??= new List<TItem>();

await HandleShiftClick( eventArgs );

if ( eventArgs.Selected && !SelectedRows.Contains( eventArgs.Item ) )
if ( eventArgs.Selected && !SelectedRows.Contains( eventArgs.Item ) && !eventArgs.ShiftKey )
{
SelectedRows.Add( eventArgs.Item );
}
else if ( !eventArgs.Selected && SelectedRows.Contains( eventArgs.Item ) && !eventArgs.ShiftKey )
{
if ( SelectedRows.Contains( eventArgs.Item ) )
{
SelectedRows.Remove( eventArgs.Item );

if ( SelectedRow.IsEqual( eventArgs.Item ) )
{
await SelectedRowChanged.InvokeAsync( default( TItem ) );
}
}
}

if ( !eventArgs.Selected && SelectedRows.Contains( eventArgs.Item ) )
await SelectedRowsChanged.InvokeAsync( SelectedRows );
}

private async Task HandleShiftClick( MultiSelectEventArgs<TItem> eventArgs )
{
if ( eventArgs.ShiftKey )
{
SelectedRows.Remove( eventArgs.Item );
SelectedRows.Clear();

if ( SelectedRow.IsEqual( eventArgs.Item ) )
var currIndex = ResolveItemIndex( eventArgs.Item );

if ( currIndex >= lastSelectedRowIndex )
{
foreach ( var item in DisplayData.Skip( lastSelectedRowIndex ).Take( currIndex - lastSelectedRowIndex + 1 ) )
{
SelectedRows.Add( item );
}
}
else
{
foreach ( var item in DisplayData.Skip( currIndex ).Take( lastSelectedRowIndex - currIndex + 1 ) )
{
SelectedRows.Add( item );
}
}

if ( !SelectedRows.Contains( SelectedRow ) )
{
await SelectedRowChanged.InvokeAsync( default( TItem ) );
}
}

await SelectedRowsChanged.InvokeAsync( SelectedRows );
else
lastSelectedRowIndex = ResolveItemIndex( eventArgs.Item );
}

protected async Task OnMultiSelectAll( bool selectAll )
Expand Down
9 changes: 8 additions & 1 deletion Source/Extensions/Blazorise.DataGrid/EventArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,12 @@ public class MultiSelectEventArgs<TItem> : EventArgs
/// </summary>
/// <param name="item">Model that belongs to the grid row.</param>
/// <param name="selected">Indicates if the row is selected or not.</param>
public MultiSelectEventArgs( TItem item, bool selected )
/// <param name="shiftKey">True if the user is holding shifg key.</param>
public MultiSelectEventArgs( TItem item, bool selected, bool shiftKey )
{
Item = item;
Selected = selected;
ShiftKey = shiftKey;
}

/// <summary>
Expand All @@ -202,5 +204,10 @@ public MultiSelectEventArgs( TItem item, bool selected )
/// Returns true if the row is selected.
/// </summary>
public bool Selected { get; }

/// <summary>
/// Returns true if user has ShiftClicked.
/// </summary>
public bool ShiftKey { get; }
}
}
2 changes: 1 addition & 1 deletion Source/Extensions/Blazorise.DataGrid/_DataGridRow.razor
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
{
@if ( ParentDataGrid.MultiSelect )
{
<_DataGridRowMultiSelect @ref="multiSelect" TItem="TItem" Item="Item" Checked="@IsSelected" CheckedChanged="@OnMultiSelectCommand" Class="@column.CellClass?.Invoke(Item)" Style="@column.CellStyle?.Invoke(Item)" Width="@column.Width" TextAlignment="@column.TextAlignment"></_DataGridRowMultiSelect>
<_DataGridRowMultiSelect @ref="multiSelect" TItem="TItem" Item="Item" Checked="@IsSelected" CheckedClicked="@OnMultiSelectCheckClicked" Class="@column.CellClass?.Invoke(Item)" Style="@column.CellStyle?.Invoke(Item)" Width="@column.Width" TextAlignment="@column.TextAlignment"></_DataGridRowMultiSelect>
}
}
else
Expand Down
60 changes: 43 additions & 17 deletions Source/Extensions/Blazorise.DataGrid/_DataGridRow.razor.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#region Using directives

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise.Extensions;
using Microsoft.AspNetCore.Components;

#endregion

namespace Blazorise.DataGrid
Expand All @@ -24,6 +22,12 @@ public abstract class _BaseDataGridRow<TItem> : BaseDataGridComponent
/// </summary>
protected _DataGridRowMultiSelect<TItem> multiSelect;

/// <summary>
/// If click came propagated from MultiSelect Check
/// Funels the selection logic into HandleClick.
/// </summary>
protected bool clickFromCheck;

#endregion

#region Methods
Expand All @@ -50,21 +54,43 @@ protected override Task OnAfterRenderAsync( bool firstRender )

protected internal async Task HandleClick( BLMouseEventArgs eventArgs )
{
await Clicked.InvokeAsync( new DataGridRowMouseEventArgs<TItem>( Item, eventArgs ) );
if ( !clickFromCheck )
await Clicked.InvokeAsync( new DataGridRowMouseEventArgs<TItem>( Item, eventArgs ) );

var selectable = ParentDataGrid.RowSelectable?.Invoke( Item ) ?? true;

if ( !selectable )
return;

if ( !clickFromCheck )
await HandleSingleSelectClick( eventArgs );

await HandleMultiSelectClick( eventArgs );
clickFromCheck = false;
}

private async Task HandleMultiSelectClick( BLMouseEventArgs eventArgs )
{
if ( ParentDataGrid.MultiSelect )
{
var isSelected = ( ParentDataGrid.SelectedRows == null || ( ParentDataGrid.SelectedRows != null && !ParentDataGrid.SelectedRows.Any( x => x.IsEqual( Item ) ) ) );
var shiftClick = ( eventArgs.ShiftKey && eventArgs.Button == MouseButton.Left );

await OnMultiSelectCommand( isSelected || shiftClick, shiftClick );
}
}

private async Task HandleSingleSelectClick( BLMouseEventArgs eventArgs )
{
// Un-select row if the user is holding the ctrl key on already selected row.
if ( ParentDataGrid.SingleSelect && eventArgs.CtrlKey && eventArgs.Button == MouseButton.Left
&& ParentDataGrid.SelectedRow != null
&& Item.IsEqual( ParentDataGrid.SelectedRow ) )
{
await Selected.InvokeAsync( default );
}
else if ( ParentDataGrid.MultiSelect
else if ( !eventArgs.ShiftKey
&& ParentDataGrid.MultiSelect
&& ParentDataGrid.SelectedRows != null
&& ParentDataGrid.SelectedRows.Any( x => x.IsEqual( Item ) ) )
{
Expand All @@ -77,18 +103,6 @@ protected internal async Task HandleClick( BLMouseEventArgs eventArgs )
{
await Selected.InvokeAsync( Item );
}

if ( ParentDataGrid.MultiSelect )
{
if ( multiSelect != null )
{
await multiSelect.OnCheckedChanged( !multiSelect.Checked );
}
else
{
await OnMultiSelectCommand( ParentDataGrid.SelectedRows != null && !ParentDataGrid.SelectedRows.Any( x => x.IsEqual( Item ) ) );
}
}
}

protected internal Task HandleDoubleClick( BLMouseEventArgs eventArgs )
Expand Down Expand Up @@ -118,7 +132,19 @@ protected internal Task OnCancelCommand()

protected internal Task OnMultiSelectCommand( bool selected )
{
return MultiSelect.InvokeAsync( new MultiSelectEventArgs<TItem>( Item, selected ) );
return MultiSelect.InvokeAsync( new MultiSelectEventArgs<TItem>( Item, selected, false ) );
}

protected internal Task OnMultiSelectCommand( bool selected, bool shiftClick )
{
return MultiSelect.InvokeAsync( new MultiSelectEventArgs<TItem>( Item, selected, shiftClick ) );
}

protected Task OnMultiSelectCheckClicked()
{
clickFromCheck = true;

return Task.CompletedTask;
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
<TableRowCell Class="@Class" Style="@BuildCellStyle()" TextAlignment="@TextAlignment">
@if ( ParentDataGrid.MultiSelectColumn?.MultiSelectTemplate != null )
{
<Label @onclick:stopPropagation>
<Label @onclick="@OnCheckedClicked">
@ParentDataGrid.MultiSelectColumn.MultiSelectTemplate( new MultiSelectContext<TItem>( EventCallback.Factory.Create( this, new Func<bool, Task>( OnCheckedChanged ) ), Checked, false, Item ) )
</Label>
}
else
{
<Label @onclick:stopPropagation>
<Check TValue="bool" Checked="@Checked" CheckedChanged="@OnCheckedChanged" CheckedExpression="@(()=> Checked)" @onclick:stopPropagation></Check>
<Label @onclick="@OnCheckedClicked">
<Check TValue="bool" Checked="@Checked" CheckedChanged="@OnCheckedChanged" CheckedExpression="@(()=> Checked)"></Check>
</Label>
}
</TableRowCell>
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ public abstract class _BaseDataGridRowMultiSelect<TItem> : ComponentBase

internal Task OnCheckedChanged( bool @checked )
{
Checked = @checked;
return CheckedChanged.InvokeAsync( @checked );
//Multi Select Checked State is bound to the Row Selected State
return CheckedChanged.InvokeAsync( Checked );
}

internal Task OnCheckedClicked()
{
return CheckedClicked.InvokeAsync();
}

protected string BuildCellStyle()
Expand Down Expand Up @@ -49,6 +54,8 @@ protected string BuildCellStyle()

[Parameter] public EventCallback<bool> CheckedChanged { get; set; }

[Parameter] public EventCallback CheckedClicked { get; set; }

#endregion
}
}