2

I have a static ObservableCollection MarketList in ViewModel and it is bound to Table in following manner:

<FlowDocumentScrollViewer Height="216" VerticalAlignment="Top" Margin="-7,2,7,0" >
    <FlowDocument>
        <Table CellSpacing="0" Name="MBPTable"  >
            <Table.DataContext>
                <MultiBinding  UpdateSourceTrigger="Explicit"  Mode="TwoWay" Converter="{StaticResource indexerConverter}">
                    <Binding Path="MarketList" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" Mode="TwoWay" BindsDirectlyToSource="True"  />
                    <Binding Path="MBPindex"  Mode="TwoWay"   />
                </MultiBinding>
            </Table.DataContext>
        <Table.Resources>
            <local:IndexerConverter x:Key="indexerConverter"></local:IndexerConverter>
        </Table.Resources>

Table contains ListView which is bound to Property of MarketList.

<ListView  Name="MarketByPriceList" Width="300" ItemsSource="{Binding MarketByPriceList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AlternationCount="2" Margin="0,15,0,0" >
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Orders"  Width="48"  DisplayMemberBinding="{Binding MBP_NoofBuy_Orders, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ></GridViewColumn>
            <GridViewColumn Header="Bid Qty" Width="48"  DisplayMemberBinding="{Binding MBPBID_Qty,  UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ></GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

This Is Convertor Method

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values != null && values[0] != DependencyProperty.UnsetValue)
        {
           // ObservableCollection<GlobalItems.Model.MarketWatchModel> allNames = (ObservableCollection<GlobalItems.Model.MarketWatchModel>)values[0];
            int index = (int)values[1];

            return GlobalItems.ViewModel.MarketWatchModelView.MarketList[index];
        }
        else
        {
            return null;
        }
    }

Binding works fine but update in collection is not reflected in UI

Nitesh
  • 7,261
  • 3
  • 30
  • 25
Nikita P
  • 41
  • 4
  • Is the collection being updated from the UI thread? If not I don't think you'll see the changes. – strattonn Aug 06 '13 at 05:52
  • how is it you are doing the update to the collection, if you are replacing the collection with a new one it won't show the changes – sergioadh Aug 06 '13 at 05:52
  • I am replacing single row in collection – Nikita P Aug 06 '13 at 05:55
  • What do you call "update in collection"? Is it an add/delete element in the collection (which should work), or an update of an element of the collection (which will work only is the elements of the collection are also bindable and used raised property changed) – Ouarzy Aug 06 '13 at 06:37

2 Answers2

9

This appears to boil down to the same problem described here, and essentially the same solution should work.

Updating (adding to or removing from) the ObservableCollection does not cause your MultiBinding to refresh because the MultiBinding is listening for a PropertyChanged event and updating an ObservableCollection only fires a CollectionChanged event. A clean workaround is to add a Binding to the Count property of your ObservableCollection in your MultiBinding. E.g.

<MultiBinding  UpdateSourceTrigger="Explicit"  Mode="TwoWay" Converter="{StaticResource indexerConverter}">
  <Binding Path="MarketList" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" Mode="TwoWay" BindsDirectlyToSource="True"  />
  <Binding Path="MBPindex"  Mode="TwoWay"   />
  <Binding Path="MarketList.Count" /> <!-- Additional Binding causes refresh when MarketList is updated -->
</MultiBinding>

Add the additional binding after all of your existing bindings so that the MultiValueConverter can just ignore the extra value. When the Count property of your ObservableCollection changes (when you add or remove items), then it will fire a PropertyChanged event and your MultiBinding will refresh.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Dan Oliphant
  • 501
  • 4
  • 6
5

I was troubleshooting the same issue, but needing it to fire not only when the count changed, but also when items were modified. Both Dan's answer and the one he linked got me pointed in the right direction, but along the way I discovered there is a better alternative to binding to the Count property. Bind to "Item[]" instead, which will fire a PropertyChange both when items are added or removed (same as Count), but also when items are rearranged or changed.

Updated version of Dan's example:

<MultiBinding  UpdateSourceTrigger="Explicit"  Mode="TwoWay" Converter="{StaticResource indexerConverter}">
  <Binding Path="MarketList" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" Mode="TwoWay" BindsDirectlyToSource="True"  />
  <Binding Path="MBPindex"  Mode="TwoWay"   />
  <Binding Path="MarketList.Item[]" /> <!-- This is the difference -->
</MultiBinding>

My source was the source code of ObservableCollection, found here: http://referencesource.microsoft.com/#System/compmod/system/collections/objectmodel/observablecollection.cs