4
votes

I'm trying to work with a datagrid using the MVVM pattern. The problem is that whenever I change the VM property which is binded to SelectedItem to null, the View doesn't "deselect" the currently selected item. This is my binding in xaml:

<DataGrid Grid.Column="0" Grid.Row="0" 
    ItemsSource="{Binding Path=Users}" 
    AutoGenerateColumns="False" 
    CanUserAddRows="False" 
    IsReadOnly="True" 
    SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">

The SelectedItem binding works from the view to the VM thus in the SelectedUser property I always have the selected object. The problem is that in the VM I'm doing some stuff which sometimes changes the SelectedUser property to null so I would expect the datagrid to deselect the row as well. Instead, it remains selected and if I try to click on the same row, the property doesn't update. If I click on any other row, the property changes as expected.

Is there a way to make the datagrid deselect if it's binded property is set to null? Also I'm looking for a MVVM solution as I don't want to write code behind. I can solve this by writing code behind so don't waste time offering such solutions :)

l.e.: this is my property in the VM:

public RPLUser SelectedUser
        {
            get
            {                
                return selectedUser;
            }
            set
            {
                selectedUser = value;
                OnPropertyChanged("SelectedUser");
            }
        }

Thanks in advance!

4
When you set the property in your viewmodel are you calling the OnPropertyChanged event to let the View know it needs to update?Purplegoldfish
Yes, I'm editing the description to mention this as well. Good question, thank you!Florin Bombeanu
Can you post the code you are using to set the property in your VM and also the code for the property itself?Purplegoldfish
Setting UpdateSourceTrigger=PropertyChanged in your binding might help.Louis Kottmann
I would try OnPropertyChanged(""); Could be something weird is going on with the binding but that does look ok. Have you tried breakpointing the set to see if the SelectedUser gets set again sometime after you have set it to NULL? Also make sure you are setting the SelectedUser property and not the variable it returns.Purplegoldfish

4 Answers

6
votes

I recommend to check the Output Window in visual studio and see if any Binding is failing.

Are you sure when you select something, the selection updates into the SelectedUser property?

Did u put a breakpoint in setter of SelectedUser and see that it is hitting when you select something on the datagrid?

The reasons for this Binding to break could be many ...

  1. SelectedUser is of different type than individual Users.
  2. SelectedUser does not match by reference with any items in Users.
  3. How and where are you setting null?

The following code in my case works perfectly fine...

    <tk:DataGrid MaxHeight="200" AutoGenerateColumns="False"
                 ItemsSource="{Binding}"
                 SelectedItem="{Binding MySelItem,
                                        ElementName=MyDGSampleWindow,
                                        Mode=TwoWay}"
                 IsReadOnly="True">
        <tk:DataGrid.Columns>
            <tk:DataGridTextColumn Header="Key"
                                   Binding="{Binding Key,
                                                     Mode=OneWay}"/>
            <tk:DataGridTextColumn Header="Value"
                                   Binding="{Binding Value,
                                                     Mode=OneWay}"/>
        </tk:DataGrid.Columns>
    </tk:DataGrid>

When I set MyDGSampleWindow.MySelItem as null, the datagrid propertly deselects. Perhaps you might need to give us more input on how are you actually setting the value as null.

5
votes

Did you try setting IsSynchronizedWithCurrentItem="True" in the xaml properties for the DataGrid? AFAIK, this will allow you to unselect it by setting the SelectedUser to null.
I cannot test it at the moment, but you could also try to add this in the setter of your property:

set
{
    selectedUser = value;
    OnPropertyChanged("SelectedUser");

    ICollectionView collectionView = CollectionViewSource.GetDefaultView(Users);
    collectionView.MoveCurrentTo(selectedUser);

}

(For ICollectionView to do anything, you will need to have IsSynchronizedWithCurrentItem set)
Like I said, I cannot test this right now. Also, the setter of the property is probably not the best place to put it. Maybe create an event handler for the PropertyChangedevent locally and put that logic there.

Let me know if it helps, else I'll see if I can run a short test...

2
votes

Yeah may need to add the XAML UpdateSourceTrigger to update the UI.

SelectedItem="{Binding SomeProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
0
votes

The DataGrid will not Deselect it automatically as DataGridRow's IsSelected property should be set to False.

You can do that by Setting a style on DataGrid.. like

    <Style x:Key="dataGridRowStyle"
           BasedOn="{StaticResource {x:Type WPFToolkit:DataGridRow}}"
           TargetType="{x:Type WPFToolkit:DataGridRow}">
        <Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
    </Style>  

The IsSelected property should be the of the object i.e in your case RPLUser should have a property Isselected

Then before you set the SelectedUser to null... just do SelectedUser.IsSelected=False

And dont forget to attach this style to the DataGridRowStyle in Datagrid

I am using WPFToolkit you can modify the style if you are targetting .NET 4.0