Disable selecting in WPF DataGrid
Asked Answered
L

13

60

How can I disable selecting in a WPFTooklit's DataGrid? I tried modifying the solution that works for ListView (from WPF ListView turn off selection), but that doesn't work:

<tk:DataGrid>
    <tk:DataGrid.ItemContainerStyle>
        <Style TargetType="{x:Type tk:DataGridRow}">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </tk:DataGrid.ItemContainerStyle>
    <tk:DataGrid.CellStyle>
        <Style TargetType="{x:Type tk:DataGridCell}">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </tk:DataGrid.CellStyle>
</tk:DataGrid>
Lowther answered 23/3, 2010 at 0:49 Comment(0)
E
-11

There is a trick for this. You can handle SelectionChanged event of the DataGrid(say dgGrid) and in the handler write:

dgGrid.UnselectAll();

It will unselect all selected row and result will be "No row selected".

Emmott answered 23/3, 2010 at 18:19 Comment(4)
Does not work: this works: #3047488Preliminaries
+1 Thats a right one :)...anyways mine is working fine in my case :)Emmott
Nikhil's version worked perfectly for me. I can edit cells directly in the DataGrid and the entire row stays unselected. Thanks Nikhil.Mutant
You should avoid interacting with view logic in the code behind/viewmodelMalraux
D
49

The clean way would be, to just override the styles of the row and the cell

<DataGrid.Resources>
    <ResourceDictionary>
        <Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
            <Setter Property="Background" Value="{x:Null}" />
            <Setter Property="BorderBrush" Value="{x:Null}" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{x:Null}" />
                    <Setter Property="BorderBrush" Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="Background" Value="{x:Null}" />
            <Setter Property="BorderBrush" Value="{x:Null}" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{x:Null}" />
                    <Setter Property="BorderBrush" Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ResourceDictionary>
</DataGrid.Resources>
Dike answered 28/3, 2012 at 17:3 Comment(5)
This disabled selection at all. I had to replace "{x:Null}" by "Transparent" to keep selection working. This is the way Mr. Snuggles recommended.Orlena
FYI, dont't forget to set <Setter Property="Foreground" Value="Black"/> in the trigger otherwise the text of the selection will be, by default, white.Equivoque
@JiBéDoublevé I just had to do this, however instead of using a hardcoded value, I put this in the DataGridCell's Triggers: <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}"/>, which sets it to what it already is. Strangely, it seems explicitly setting a color on the column definition also removes the color change, without the need for a setter.Cristinacristine
If you want to keep settings of a default style (e. g. by Material Design), then you can add this to the style tags: BasedOn="{StaticResource {x:Type DataGridCell}}" and BasedOn="{StaticResource {x:Type DataGridRow}}" ... As result only the border is removed, not the whole default style.Vestal
What do you do about all the controls still turning blue? The textblock backgrounds in each cell turn blue, and I have dropdowns and buttons in datatemplates that have a blue border when the row is selected.Binge
M
37

To completely disable selection of rows in a DataGrid, you could do the following:

<DataGrid>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="IsHitTestVisible" Value="False"/>
        </Style>
    </DataGrid.RowStyle>
    <!--Other DataGrid items-->
</DataGrid>

This could be considered more favorable than setting <Setter Property="IsEnabled" Value="False"/> due to the fact that doing the aforementioned technique causes the style of the row to change. It also does not disable context menus from appearing when right-clicking.

Lastly: it is important to note that setting "IsHitTestVisible" to "False" disables all interaction with the rows, including editing.

However, if all you want to do is change the styling of the row when selected, please view the answers here.

Malraux answered 5/8, 2016 at 18:25 Comment(4)
This answer kinda saved my life!Mateo
Old answer but I'd like to comment on this. My solution has Rows with a separate ViewModel. In order to totally disable the datagrid you can use DataGrid.Style and TargetType = "DataGrid". Because I need to control when selecting items is allowed I use a Value ="{Binding SomeProperty}" and then that property has to be on the DataContext. Gave me a binding error if the property was on the main DataContext when ussing a RowStyle setup.Heraldry
This works, but prevents clicking any buttons.Alizaalizarin
@Rugbrød: "it is important to note that setting "IsHitTestVisible" to "False" disables all interaction with the rows, including editing." This includes clicking buttons.Malraux
N
27

Simply add IsHitTestVisible="False" to DataGrid definition.

Nonobservance answered 12/6, 2013 at 10:1 Comment(3)
This prevents the vertical scrollbar from responding to the mouse.Teakettle
Works like a charm... and if you bind the value to an INPC property, then you can be selective about which rows are selectable :-)Cobos
Along with the vertical scrollbar issue, this also disables mouse clicking for child controls.Adopted
U
12

All of the above are good ideas for easy hacks. However, they aren't doing exactly what is asked. The other answers are telling us how to unselect something selected by the user or hide the fact that something was selected by the user.

However, I understand why these answers are given. It is not easy to provide the real solution.

The real solution is to prevent selection in the first place, which it is not straightforward but it is doable with a few easy steps.

Answer 1. You have to copy the style in Expression Blend (or find a copy of the style somewhere). 2. Change a single ItemPresenter setting. It was enough for me to set IsHitTestVisible="False" on the ItemPresenter.

If you need more details, or an in-depth walk-thru for doing this, see my blog post:

How to disable row selection in a WPF DataGrid?

Unpen answered 24/5, 2011 at 19:23 Comment(2)
That's not quite correct either - it stops clicks happening on the DataGridCells, which often is not desirable.Glee
Agreed. One of these days I am going to have to find a solution that disables select but allows click.Unpen
R
9

As pointed out by Sonic Soul here, viky's solution doesn't actually work.

Here is actual working code to disable selection in a DataGrid:

grid.SelectionChanged += (obj, e) => 
  Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => 
    grid.UnselectAll())); 
Rudolphrudwik answered 16/6, 2010 at 4:3 Comment(1)
This method should be combined with setting the DataGrid SelectionMode property to "Single" ... otherwise you can select multiple cells before the event is fired.Jemy
O
7

The only proper way I found to do this is to disable IsHitTestVisible property on DataGridRowStyle.

Click events will still register despite the naming. Make sure you do not change this property on the whole DataGrid unless you also want to disable scrolling.

A clean way of doing this is through a new Style in your static resources (copying other setters as appropriate)

        <Style x:Key="DataGridUnselectableRowStyle" TargetType="{x:Type DataGridRow}">
            <Setter Property="IsHitTestVisible" Value="False"/>
        </Style>

and then binding it on your DataGrid

        <DataGrid
            RowStyle="{StaticResource DataGridUnselectableRowStyle}" >
            <!-- Contents -->
        </DataGrid>
Outpoint answered 15/6, 2017 at 15:43 Comment(0)
F
4

Another simple way is to change the Selection Style with an IsSelected Trigger to Transparent.

Fancier answered 25/7, 2010 at 14:8 Comment(0)
Q
4

In case you are using alternate colors:

<Style TargetType="{x:Type DataGrid}">
    <Setter Property="RowBackground" Value="#badeee"/>
    <Setter Property="AlternationCount" Value="2" />
    <Setter Property="AlternatingRowBackground" Value="#92cce5"/>
</Style>

<Style TargetType="{x:Type DataGridCell}">
    <Style.Triggers>           
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="Foreground" Value="Black"/>
        </Trigger>
    </Style.Triggers>
</Style>

<Style TargetType="{x:Type DataGridRow}">
    <Style.Triggers>
        <Trigger Property="ItemsControl.AlternationIndex" Value="0">
            <Setter Property="Background" Value="#badeee"></Setter>
            <Setter Property="BorderBrush" Value="#badeee"></Setter>
        </Trigger>
        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
            <Setter Property="Background" Value="#92cce5"></Setter>
            <Setter Property="BorderBrush" Value="#92cce5"></Setter>
        </Trigger>
    </Style.Triggers>
</Style>
Qianaqibla answered 10/5, 2012 at 14:11 Comment(0)
J
3

Based on some answers from this thread I came up with the solution.

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
        <Setter Property="IsHitTestVisible" Value="False"/>
    </Style>
</DataGrid.RowStyle>

This one does not make the datagrid greyed out, nor the rows, cells or header. It allows scrolling and does not require code behind.

Joke answered 26/6, 2023 at 15:52 Comment(1)
This is just the same answer as the current top.Superable
W
2

If someone else is facing same problem, they may find it helpful.

We had a requirement to disable few rows on datagrid, but at the same time allow ARROW key navigation on them. This is why we had to switch to 'IsHitTestVisible' instead of controlling 'IsEnabled' property. So we couldn't adopt to above solution of switching to 'IsEnable' property.

Here is how I ended up solving this issue. I created a new attached property (RowEnable) for DataGridRow. This attached property can be bind to a viewmodel property to control 'virtual' enable and disablement. I also created a new style for DataGridCell where I am setting 'IsHitTestVisible' to false based on the same viewmodel property. So, consider it like a row which mouse/keyboard can see, but can't see its cells/columns. This means now I can style the row based on new attached property (RowEnabled) to look disabled/enabled. At the same time, I can view tooltips for these rows which are virtually disabled.

Wagram answered 17/5, 2015 at 18:23 Comment(0)
V
0

I needed a code behind solution. This works for me:

controlGrid.SelectedCellsChanged += (sender, e) =>
    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, new Action(() =>
        controlGrid.UnselectAll()));
controlGrid.Columns.Clear();

Because it sometimes flickers, the BackgroundProperty also be set to transparent.

Style dataGridCellStyle = new Style(typeof(DataGridCell));
Setter newSetterCell = new Setter(DataGridCell.BackgroundProperty, Brushes.Transparent);
dataGridCellStyle.Setters.Add(newSetterCell);
controlGrid.CellStyle = dataGridCellStyle;
Vivia answered 14/6, 2019 at 13:24 Comment(0)
D
0
<DataGrid isEnabled="False">
</DataGrid>

This is the simplest way to directly answer your question: disable selecting in WPF Datagrid.

Dissimilate answered 5/9, 2020 at 21:18 Comment(8)
Code-only answers are discouraged on Stack Overflow because they don't explain how it solves the problem. Also, please edit your answer to explain how it works and how it improves on the many other upvoted answers this question already has, so that it is useful to other users with similar issues.Typeset
I don't think it would be a good idea to delete one of only two clear, succinct, and correct answers to the question. You don't need to touch the codebehind, you don't need styles, you don't need to mention alternate colours. All you need is a well-placed property.Dissimilate
If that's why you think this is a good answer, then add that information into your answer! Users may not know if this even works with so little code when the other answers are more comprehensive, so you need to tell them how it works and why they don't need the rest. This is why code-only answers are discouraged, as I explained... if users don't understand how or why your answer will work (especially when there are so many other upvoted ones), then it's not very helpful to them, or worse - they might even think its wrong.Typeset
I'm amazed at the high standards you hold my answer to while having such low expectations of readers. I think they'll manage to copy and paste the property into their data grid and see that it works. Half the stuff you want me to bloat the answer with is offtopic: it doesn't answer the question.Dissimilate
That not how Stack Overflow works. It’s purpose is to act like an “encyclopaedia” for programming questions, and this answer was flagged by the community as low quality for lack of detail.Typeset
We agree that answers should help the asker to solve their problem. This answer does so, We both want to help answer people's questions. I suggest we move on to the next person's question and leave this answer as at least good enough.Dissimilate
As I said, this answer was flagged by the community, I’m just one of the reviewers, so it’s not me you need to convince.Typeset
This will make the whole datagrid be grayed out, most likely now what people are after.Symphonia
E
-11

There is a trick for this. You can handle SelectionChanged event of the DataGrid(say dgGrid) and in the handler write:

dgGrid.UnselectAll();

It will unselect all selected row and result will be "No row selected".

Emmott answered 23/3, 2010 at 18:19 Comment(4)
Does not work: this works: #3047488Preliminaries
+1 Thats a right one :)...anyways mine is working fine in my case :)Emmott
Nikhil's version worked perfectly for me. I can edit cells directly in the DataGrid and the entire row stays unselected. Thanks Nikhil.Mutant
You should avoid interacting with view logic in the code behind/viewmodelMalraux

© 2022 - 2024 — McMap. All rights reserved.