2
votes

The Setup

  • I have a DataGrid that holds a list of custom types ("Previous Documents") and binds to them. That part works correctly.
  • I have bound the SelectedItemProperty of the datagrid to a property on my ViewModel called CurrentlySelectedPreviousDocument
  • I have the left-click action of the datagrid bound to a command called OpenPreviousDocumentCommand
  • The OpenPreviousDocumentCommand runs a method called OpenSelectedPreviousDocument()
  • OpenSelectedPreviousDocument() uses the CurrentlySelectedPreviousDocument property to copy a file to the temporary directory and open it.

The Problem

  • This code works, but only if you click on the first item in the datagrid.
  • For every other item in the datagrid, it appears that CurrentlySelectedPreviousDocument is shown as null, so all of the properties are null.

More scenarios to help describe the problem:

  • When I load the application, no rows are selected.
  • If I double-click the first item at any point, it opens, even after clicking other items and seeing errors.
  • If I double-click the second or third items first, I receive the error.
  • If I double-click the first document to open it, then single-click another row to ensure it is selected, and then double-click on the other row, I still receive the error.
  • If I double-click the first document to open it, then click one of the faulty rows and receive an error, and then click on the first row again, it still works.

Things I've Tried So Far:

  • Updating the bingding mode to TwoWay
  • Adding an UpdateSourceTrigger = PropertyChanged
  • Checked the output window; no invalid bindings detected.

The Code

XAML DataGrid bindings:

<DataGrid 
    x:Name="PreviousDocumentsDataGrid"
    ItemsSource="{Binding PreviousDocumentsList}" 
    SelectedItem="{Binding CurrentlySelectedPreviousDocument, Mode=OneWayToSource}" 
    SelectionMode="Single"
    SelectionUnit="FullRow" 
    AutoGenerateColumns="False" 
    IsReadOnly="True" 
    HorizontalGridLinesBrush="LightGray" 
    VerticalGridLinesBrush="LightGray" 
    BorderBrush="Transparent" 
    Visibility="{Binding PreviousDocumentsFound, Converter={StaticResource BoolToVisConverter}}">
    <DataGrid.InputBindings>
        <MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenPreviousDocumentCommand}"/> 
    </DataGrid.InputBindings>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Reference Type" Binding="{Binding ReferenceType}"/>
        <DataGridTextColumn Header="Category ID" Binding="{Binding Category}"/>
        <DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
        <DataGridTextColumn Header="Document Timestamp" Binding="{Binding Timestamp}"/>
    </DataGrid.Columns>
</DataGrid>

The ViewModel definition of CurrentlySelectedPreviousDocument:

public VEDocument CurrentlySelectedPreviousDocument
{
    get { return _currentlySelectedPreviousDocument; }
    set { _currentlySelectedPreviousDocument = value;
    OnPropertyChanged("CurrentlySelectedPreviousDocument");} //TODO: Is the on propertychanged actually necessary here?
}

Command Definition:

public ICommand OpenPreviousDocumentCommand
{
    get
    {
        return _openPreviousDocumentCommand ??
               (new CommandHandler(OpenSelectedPreviousDocument, _canExecuteCommands));
    }
}

Method in the ViewModel to open the document (uses the viewmodel property)

public void OpenSelectedPreviousDocument()
{
    var docToOpen = CurrentlySelectedPreviousDocument;
    ...etc. etc.
}
1
What happens when you left click once on the new item and only then double-click? May it be that the selected property is not updated yet?meilke
@meilke great idea. I looked into it, but unfortunately this is not the case. I tried double-clicking the first row (successful), clicking the second row once to highlight it (successful), and then double-clicking the second row (failure). I'm thinking the issue is somewhere in the binding back to CurrentlySelectedPreviousDocument, I just can't figure out where.SeanKilleen
Did you deselect unintentionally by double-clicking? Is that possible?meilke
Updated the question to include some scenarios that I've tried (see the "problem" section). It looks like no matter what, the first row binds correctly to the property, but when selecting other rows, the property becomes null. I can't get rows other than the first row to work, but I can't get the first row to ever not work.SeanKilleen
@sexta13 thanks for jumping in to help out. :) My understanding of OneWayToSource is that it flows from the UI to the viewmodel but the viewmodel changing the property doesn't affect the UI. That's what I want since this property is purely being drawn from the UI. However, I tried TwoWay just to make sure. Same problem.SeanKilleen

1 Answers

1
votes

A lesson in debugging and posting questions -- this one is entirely on me.

What I did not mention, but should have, is that in offline mode I was using a fake service to return the list of documents.

If I'd mentioned that, I could have pasted the code and folks could have seen that my fake service wasn't returning a location for two of the documents (hence my issue).

I created a piece of debugging code that outputted the locations from the list itself when my viewmodel was opened. Doing this helped me see that it was the list that had the problem, not the binding. My assumption that I got the binding wrong (due to my inexperience with WPF) was actually a false one.

Big Thanks to sexta13 and meilke for helping me rule out other potential issues.

Lessons Learned / Reinforced:

  • When debugging, start at the source. Challenge your assumptions at each step of the process until
  • When using a fake anything, standardize the method for it returning values so that they will all be in the same format. I normally do that but didn't this once as a shortcut, and it bit me.
  • Mention and post the code that the situation touches, even if it seems unrelated. Had I posted the fakes and their code, someone likely would have helped me see the issue very quickly.