1

Initially I posted this to the PRISM4 forum but got a suggestion that I should try this forum as well:) I'm using WPF4 BTW...

I'm running PRISM4 and I've been struggling to get my data binding to work. I'm following the MVVM pattern and have a view model which initially loads data from a RDBMS and wraps it in an ICollectionView.This works perfectly, the data is displayed in the bound DatGrid, but I'm struggling in my eforts when trying to persist changes made to the data which is presented in a DataGrid declared below.

The view model publishes the ICollectionView through a read/write property, "Results", which, as you can see has a binding mode of "TwoWay". I thought this would be enough to persist the changes made to the state of the checkboxes but no:( I've experimented with a number of ways to accomplish this but the state of the checkbox is not propagated back to the view model. I've intercepted the call to the "PlotClicked" method which is an ICommand object but the argument being passed has an unchanged "Plot" attribute! This is especially obvious when I click one of the column headers and the view is sorted - the checked rows are unchecked which is the default state of the checkboxes when retrieved from the db.

What am I doing wrong here?

Many thanks in advance - I'm really stuck here:( /Peter

<DataGrid Grid.Row="0" Name="gridResults" ItemsSource="{Binding Results,Mode=TwoWay}" AutoGenerateColumns="False">
 <DataGrid.Columns>
  <DataGridTemplateColumn Header="Plot">
   <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
     <CheckBox IsChecked="{Binding Path=Plot, Mode=TwoWay}"
         HorizontalAlignment="Center" 
         Command="{Binding Path=DataContext.PlotClicked,Mode=OneWay, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}" 
         CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}"/>
    </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>

...

I tried out the suggestions pointed out to me. This is what I've done:

  1. In the view-model I changed the Result property from ICollectionView to OC

    public ObservableCollection Results { get; set; }

  2. Added the following template resources for the UserControl making up the View

  3. Added the following code to the DataGrid in the "Columns" section

        <DataGridTemplateColumn
            Header="cbTest"
            x:Name="cbTest"
            CellTemplate="{StaticResource IsSelectedColumnTemplate}"
            CellEditingTemplate="{StaticResource IsSelectedColumnTemplateEditing}"
            CanUserSort="True"
            Width="Auto"
            />
    

After having made those changes I experimented with various settings for the UpdateSourceTrigger in the IsChecked="{Binding mentioned... in (2) above with no effect. The changes I make to the checkboxes are not transferred back to the view-model's ObservableCollection.

Again, many thanks for trying to help me out here!

* UPDATE * Now I've experienced something REALLY SPOOOOKY:( This is what I've done:

public class ResultViewResult : IReslutViewResult
{
    public bool Plot { get; set; }
    public Guid ResultId { get; set; }
    public DateTime Generated { get; set; }
    public int Duration { get; set; }
    ...

This didn't work in a sense that the 'Plot property' could NEVER be set to true by clicking the checkbox column in the DataGrid! Now I did the following:

public class ResultViewResult : IReslutViewResult
{
    private bool _plot;
    public bool Plot
    {
        get
        {
            return _plot;
        }
        set
        {
            _plot = value;
        }
    } 
    public Guid ResultId { get; set; }
    public DateTime Generated { get; set; }
    public Guid ResultId { get; set; }
    public DateTime Generated { get; set; }
    public int Duration { get; set; }
    ...

The result you may ask? It works and the 'Plot' is correctly set! Now, I thought, this is weird!!! So what I did was the following (simply commenting out the private var and get/set code):

public class ResultViewResult : IReslutViewResult
{
    public bool Plot { get; set; }
    //private bool _plot = false;
    //public bool Plot
    //{
    //    get
    //    {
    //        return _plot;
    //    }
    //    set
    //    {
    //        _plot = value;
    //    }
    //} 
    public Guid ResultId { get; set; }
    public DateTime Generated { get; set; }
    public int Duration { get; set; }
    ...

Ok, what about the result? IT WORKS!!!??? I'm stunned... I mean what's the difference between the first and the last???? I feel VERY awkward about this - I mean I want to know WHAT'S going on behind the scene here... :(

Kodo
  • 11
  • 2
  • Hi Kodo, and welcome to Stack Overflow. It seems your question has already been asked before: see http://stackoverflow.com/questions/2929627/wpf-4-0-datagrid-template-column-two-way-binding-problem. As a result of this, I'm afraid that there's a chance your question might be closed as an 'exact duplicate'. Either way, I hope the question I linked to helps you. – Luke Woodward Jul 25 '11 at 09:16
  • Hi! Thanks for your suggestion, however it didn't help me out here so I added some additional information... – Kodo Jul 25 '11 at 12:56
  • If you put a breakpoint in your `Plot` property, does the get and set methods get called correctly? – Rachel Jul 25 '11 at 13:37
  • Hi Rachel! I'm stunned! Please have a look in the "UPDATE" section above... – Kodo Jul 26 '11 at 09:13
  • Does anybody have an explanation/suggestion to the strange behavior? I've made numerous clean/rebuild of the project but the problem has remained 'til I started to change the get/set code and putting it back... Furthermore I haven't done any automatic updates recently which may have changed some assemblies. Í prefer to know and understand what's going on but in this case I'm in "lost in binary space"... Of course I'm happy that it works, but I have absolutely NO clue as to what MADE it work:( – Kodo Jul 27 '11 at 07:17

2 Answers2

0

Not sure about that, but I'd suggest you to try with an ObservableCollection used as ItemsSource . I had a lot of problems like that before, all of them were solved using this kind of collection (which is btw faster and less consuming than a classic collection for refreshing purposes).

Also, try to add in the IsChecked binding the following: UpdateSourceTrigger=PropertyChanged, this could do the trick, I think the only problem here is that the source isn't updated at the right time!

Damascus
  • 6,553
  • 5
  • 39
  • 53
  • Hi! Thanks for your suggestion, however it didn't help me out here so I added some additional information... – Kodo Jul 25 '11 at 12:56
0

Not sure if this is the issue in your case, but the DataGrid uses a variation of databinding that will not commit the changes to the source until you move off the row. This is called a BindingGroup. Maybe you're not seeing the values committed because you haven't moved off the row yet?

http://blogs.msdn.com/b/vinsibal/archive/2008/08/11/wpf-3-5-sp1-feature-bindinggroups-with-item-level-validation.aspx

One other possibility is that the binding path is somehow not correct? Have you checked the output window in VS to see if it's reporting any binding path failures?

NathanAW
  • 3,329
  • 18
  • 19
  • Hi Nathan! I've scrolled down a couple of rows and selected another row further down but no exception is displayed in the VS Output Window... Thanks anyway – Kodo Jul 25 '11 at 13:43