0

i created a window with a DataGrid in it which is bounded to an ObservableCollection:

<GroupBox Header="Kunden" Grid.Column="0">
            <DataGrid AutoGenerateColumns="False"
                          Height="Auto"
                          HorizontalAlignment="Stretch"
                          x:Name="customersDataGrid"
                          VerticalAlignment="Top" Width="Auto"
                          ItemsSource="{Binding Path=Customers, Mode=TwoWay}"
                          IsReadOnly="True"
                          CanUserResizeColumns="False"
                          ClipboardCopyMode="IncludeHeader"
                          CanUserAddRows="False"
                          SelectionMode="Single"
                          ColumnHeaderStyle="{DynamicResource ResourceKey=DataGridColumnHeaderBold}"
                          GridLinesVisibility="None"
                          Background="White"
                          IsSynchronizedWithCurrentItem="True"                              
                          FontFamily="Century Gothic"
                          SelectedItem="{Binding Path=SelectedCustomer,
                                                 Mode=TwoWay,
                                                 UpdateSourceTrigger=PropertyChanged}">
                <!--Trigger-Verhalten-->
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <catel:EventToCommand Command="{Binding CustomerSelectionChangedCmd}"
                                                        DisableAssociatedObjectOnCannotExecute="False"
                                                        PassEventArgsToCommand="True" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>

                <DataGrid.Columns>
                    <DataGridTextColumn Header="Id"
                                        Binding="{Binding Path=CustomerId}"
                                        FontSize="14" Width="Auto" />
                    <DataGridTextColumn Header="Name"
                                        Binding="{Binding Path=CustomerName}"
                                        FontSize="14"  Width="Auto"/>
                </DataGrid.Columns>
            </DataGrid>
        </GroupBox>

Customers=ObservableCollection (Properties of Customer: CustomerId, CustomerName)

When i set SelectedCustomer to null in the ViewModel, the datagrid will be unselected. But i need the datagrid to stay unselected after the window is started. I tried to set the SelectedCustomer in the contructor of the ViewModel but it did not work. It only works if i do this in the code behind: customersDatagrid.SelectedItem=null.

Is there any solution doing this in a MVVM way?

Thanks in advance and best regards,

Minh

Benjamin Martin
  • 576
  • 1
  • 8
  • 27
  • I suspect that *you* are setting the `SelectedItem` somewhere because if you add a basic `DataGrid` to a new empty WPF Application, you will see that no row is selected by default. – Sheridan Sep 20 '13 at 11:01
  • I have deleted the SelectedItem binding and the datagrid is still selected :(. – Benjamin Martin Sep 20 '13 at 11:09
  • Can you share your view model? – TrueEddie Sep 20 '13 at 11:41
  • Hi i can't post the viewmodel because its to complex and i am using a lot of userdefined controllers/classes which are resolved via interfaces and ninject. But basically its nothing special, it's just an ObservableCollection which is bounded to the ItemsSource-Property and a Customer(has only two property int, string for name and id) object which is bounded to the SelectedItem. You can reproduce the effect if you make a clean project with a datagrid in it which is bounded to observable collection. – Benjamin Martin Sep 20 '13 at 12:25
  • Why is your grid's `SelectedItem` binded in a `TwoWay` mode? do you have a usecase where the selected item changes not directly from the grid? if not, don't bind it directly – Omri Btian Sep 20 '13 at 14:59
  • Can you set the SelectedIndex property to -1? – user2378527 Sep 20 '13 at 20:04
  • Hi i did set it to -1 and it didnt work :(. I also need to change the selected item from the gui. – Benjamin Martin Sep 23 '13 at 10:03

3 Answers3

1

Hi Guys thank you very much for your answers, especially Geert for the constructive hint. I could solve this problem after the code behind file is deleted.

WHY? This could be the answer:

From the XAML file two files are created during compilation:

  1. MainWindow.g.cs – where the class MainWindow sits. This class loads the second file –

  2. MainWindow.Baml which is our XAML after some sort of compilation (it's actually pre-tokenization – parsing the file in advance so that the loading in runtime would be faster than loading a non-parsed XML file)

The loading and connecting of those two files are being performed in the method InitializeComponent that resides within MainWindow.g.cs, only… now that we've got rid of the CodeBehind nobody calls this method. What happens is that nothing loads the BAML file and hence everything stays completely empty.

I got it from here: http://www.codeproject.com/Articles/377094/How-to-make-WPF-behave-as-if-MVVM-is-supported-out

I think the InitializeComponent() is being called after the ViewModel is constructed. That's why i saw the SelectedCustomer property was set the second time after it was set to null by the vm constructor.

Benjamin Martin
  • 576
  • 1
  • 8
  • 27
  • Good to hear that your issue is solved. However I strongly recommend that you use a Catel view base (catel:UserControl or catel:DataWindow) which fully takes care of this for you. – Geert van Horrik Sep 25 '13 at 18:23
  • I tried it before but for some reason the loading process was significant slow :(. Maybe i have done something wrong i will take a look at the tutorial when i can. Thx again :). – Benjamin Martin Sep 26 '13 at 08:09
  • Good read: https://catelproject.atlassian.net/wiki/display/CTL/Performance+considerations – Geert van Horrik Sep 26 '13 at 11:58
0

I think the Initialize method on the view model is the place to be. This method is called when the view is loaded and is the perfect way to unselect an item if it selects one by default.

Geert van Horrik
  • 5,689
  • 1
  • 18
  • 32
0

I wouldn't recommend you to bind the SelectedItem of your grid.

Instead, send it as a parameter in your command:

 <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding CustomerSelectionChangedCmd}"  CommandParameter="{Binding ElementName=customersDataGrid, Path=SelectedItem}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

In your viewModel, proccess the command with the selected item

    CustomerSelectionChangedCmd= new DelegateCommand<object>(selectedItem => 
    {
        var selected = selectedItem as Customer;

        // Do whatever you want with selected customer ...

    });

and in the Grid definition in xaml, set initial selectedItem to null

 SelectedItem="{x:Null}"

This way until the SelectionChanged event is fired for the first time, the SelectedItem will be null.

Omri Btian
  • 6,499
  • 4
  • 39
  • 65
  • The code example uses `InvokeCommandAction` instead of `catel:EventToCommand` since i'm not familiar with `Catel` framework but the logic's the same ... – Omri Btian Sep 20 '13 at 14:56
  • This is good, but I think the user wants to be able to control the selection of the grid (which you MUST bind for). – Geert van Horrik Sep 20 '13 at 15:58
  • @GeertvanHorrik Not sure I understand what you mean ... The user will control the selection of the grid, which will raise the `SelectionChanged` event, which will send your viewModel the selected item, and let you do whatever you want with it ... – Omri Btian Sep 20 '13 at 16:42
  • Yep, but you say: "I wouldn't recommend you to bind the SelectedItem of your grid." But that is what the user needs because he actually wants to control the selection. – Geert van Horrik Sep 20 '13 at 18:24