none
Please, approve the bug!

    Question

  • Please, approve the bug!
    The link:
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=389689

    Description:
    When you're binding to a more than one DataView on the same table directly, event notifcations stops working.

    Strangelly, this issue doesn't occurs when binding via WinForm's BindingSource and specifiyng DataSet as source and table name as member.

    Some links:
    other problems related to dataView:
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=314279
    (my report, no reaction, just closed):
    -and-
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361248

    My previous report (no reaction, just closed):
    https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=339740&SiteID=212

    Threads on MSDN Forums: // I'll create new one soon, see the comments
    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/33442f0d-96a2-402c-91c4-d4c7b991c93a
    -and-
    http://forums.msdn.microsoft.com/en-US/wpf/thread/737889e6-6315-4d72-9563-8104b5e0429f

    P.S.
    This post will be duplicated on another threads, because the bug touches implementation of binding at WPF and WinForms.

    Please, help me contact directly with ADO.NET or WPF Testing teams. I've feedbacked this bug first time 8 month ago and there is no reaction but "there is no workaround".

    my mail: sinix DOT 2005 AT gmail DOT com.

    Thanks!
    Friday, December 26, 2008 7:47 AM

All replies

  • I've found some cases when this kind of issues were raised and I don't think that this is really a bug. I'd say it's a misconception issue, mainly for ASP originally coders.

    What happens in ASP is that, from what I've seen, usually binding is used on value types directly or using some kind of heavy control binder that is heavy because it duplicates information.

    In WPF, you actully bind to the reference types and here some issues are raised. It's cool to have some easy to read code but when you are accessing the same reference type object twice and you really don't know what this means memorywise, you'll be in trouble. That's why most of the controls that have an ItemsSource property also have IsSynchronizedWithCurrentItem property (that usualy has true as default) to prevent this kind of trouble.

    Say you have you are the manager of a table a some control tells you to select one of the items and them another control tells you to select another. When you get back to "talk" to the first control you're bound to have some misunderstandings.

    Any way...just an opinion...

    Bigsby, Lisboa, Portugal
    Sunday, December 28, 2008 12:37 AM
  • Bigsby:
    No, it's a bug, not misconception. There are no official docs saying: "Hey, don't bind to DataView, it doesn't works!" or "You should implement your custom binding wrappers, have a nice day!" or "There is no workaround, take away!".

    There's CollectionViewSource to rule them all. Siplified, it is as BindingSource for WinForms... partially ;). It should create special CollectionView for DataView providing correct behavior. It doesn't.


    2 all: 
    Hmm... It looks strange for me that there is no official comments neither reaction. This issue is critical for big part of the LOB apps, isn't it?

    I've found one note at MSDN [ms-help://MS.MSDNQTR.v90.en/dv_fxmclidata/html/3d2c43f6-462b-4d35-9c86-13e9afe012e1.htm]:

    "You can simple-bind or complex-bind to the data within a data view, but be aware that you are binding to a fixed "picture" of the data rather than a clean, updating data source."

    Does this mean DataView is supposed to be read-only by-design? If you'll see DataView's page at MSDN:

    "... Represents a databindable, customized view of a DataTable for sorting, filtering, searching, editing, and navigation ... A major function of the DataView is to allow for data binding on both Windows Forms and Web Forms."

    What I'm missing?

    Monday, December 29, 2008 1:43 AM
  • This is a bug in ADO.NET code, to workaround this issue, you need to dispose the previous DataView before working with the new DataView, here is a working example:

    <Window
            x:Class="MDBinding.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MDBinding"
            Height="150" Width="300">
      <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
          <Button
                  Width="80" Height="30"
                  Content="Reset" Click="ResetClick"/>
          <Button
                Width="80" Height="30"
                Content="Update" Click="UpdateClick"/>
        </StackPanel>
        <TextBlock
          x:Name="textBlock"
          Text="{Binding Path=ID}"/>
      </DockPanel>
    </Window>

    public partial class Window1 : Window
    {
        DataView dataView = null;
        DataTable masterTable = null;
        public Window1()
        {
            InitializeComponent();
            SetupData();
            this.Loaded += delegate
            {
                SetSource();
            };
        }

        private void SetupData()
        {
            masterTable = new DataTable("Master");
            masterTable.Columns.Add("ID", typeof(String));
            masterTable.Columns[0].Unique = true;
            masterTable.Rows.Add(0);
        }

        private void SetSource()
        {
            if (dataView != null)
            {
                dataView.Dispose();
            }
            dataView = new DataView(masterTable);
            var binding = new Binding("ID") { Source = dataView[0] };
            textBlock.SetBinding(TextBlock.TextProperty, binding);
        }

        private void ResetClick(object sender, RoutedEventArgs e)
        {
            SetSource();
        }

        int i = 1;
        private void UpdateClick(object sender, RoutedEventArgs e)
        {
            if (masterTable != null)
            {
                masterTable.Rows[0][0] = "Item" + i++.ToString();
            }
        }
    }

    Thanks

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Monday, December 29, 2008 10:30 AM
  • Thanks for answering! I'm glad - somebody is still with me:)

    Calling Dispose() on DataView helps inside primitive scenarios only. There're a lot of complex cases I couldn't extract as a sample. One of the simpliest: if I use complex path inside ListView's DataTemplate (such as "RelationName/ColumnName"), the binding notifications stops working too. It occurs rarely and I cannot find proper way to represent this. There is no simple way to use DataView on parent DataTable (however, there is workaround - use custom converter wrapping the dataview. Of course, it's slow enough).

    Please, help me contact with WPF testing team or ADO testing team. I''ll be happy to get any comment from Beatriz Stollinz (Beatriz Costa), she is one of WPF testing team and she's blogging about WPF binding issues.

    Thanks.

    And please, vote for this bug to resolve!

    Friday, January 02, 2009 5:55 AM
  • -> if I use complex path inside ListView's DataTemplate (such as "RelationName/ColumnName"), the binding notifications stops working too.

    This is a separate issue, in this thread, we are focusing on the potential ADO.NET bug when it comes to multiple DataView over a single DataTable. You could start another thread for additional issue you've encountered.

    -> Please, help me contact with WPF testing team or ADO testing team. I''ll be happy to get any comment from Beatriz Stollinz (Beatriz Costa), she is one of WPF testing team and she's blogging about WPF binding issues.

    I've redirected this thread to the ADO.NET team, I will try to loop Beatriz in If I can.

    Thanks



    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Friday, January 02, 2009 10:28 AM
  • Thanks again!

    About complex path binding: it seems to be same bug, because it occurs at the same time, but sometimes doesn't fixing with Dispose() on parent DataView.

    WinForms BindingSource (precisely, CurrencyManager) somehow fixing this bug - all works fine. Is it possible to create specialized CollectionView for DataView?

    Sunday, January 11, 2009 3:41 AM
  • I am not aware of the issue with "complex binding path", I would greatly appreciate it if you could make a repro, and send it to me for research, to further elaborate the previous issue with ADO.NET's DataView, if you use reflector the examine of the code of  DataView.OnListChanged, you will find something like the following:

    if (0 <= e.NewIndex) {

        DataRow dr = GetRow(e.NewIndex);

        if (dr.HasPropertyChanged) {

            col = dr.LastChangedColumn;

            propertyName = (null != col) ? col.ColumnName : String.Empty;

        }

        dr.ResetLastChangedColumn();

    }


    So if you have multiple DataViews which monitors the single DataTable, only the first one will win out, the subsequent change notification is cleared by calling dr.ResetLastChangedColumn() method.

    If this is a blocking issue for you, you could directly call PSS for further assistance.

    Thanks

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Monday, January 12, 2009 3:49 AM
  • Marco Zhou:

    Sorry, I couldn't find any way to contact you (except your blog, of course), so I've updated my feedback (first link at start of this thread) and add second edition of the repro code (see DataViewBindingBug v1.1 (1-to-1 binding sample added).zip)

    In case there will be troubles with downloading from the connect site (he-he :( ) here is rapidshare link:

    http://rapidshare.com/files/182344816/DataViewBindingBug_v1.1__1-to-1_binding_sample_added_.zip.html

    Also, I've found another one "dead thread" on the same issue:
    http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/64ac3723-aa4a-42a2-86e7-c06b62d2f3eb/

    P.S.
    Sorry for partial offtop: Is there "standard way" to bind to the parent DataRow of binded one? It works into reversed direction, yes (returns DataView). Also, it's possible to bind to the Row.ParentXXX navigating property if I'm using typed dataset, but it requries manual implementation of INotifyPropertyChanghed for child and parent rows (ther is no out-of-the-box) notifying for navigating properties.
    Monday, January 12, 2009 8:07 AM
  • I think I only need the code who domonstrates how the complex data binding path doesn't work here, I don't need the code which uses multiple DataView, since this has been proven to be buggy, I think we'd better try split and isolate the issues here, and shoot them one by one.

    We forum support engineer have limited time frame per thread, so We cannot spend too much time in handling a single thread, we usually have 30 threads to handle per day, so you'd better try isolating the issue here.

    As I've said, you could directly call the PSS if this is an important and blocking issue for you.

    If this has been officially proven to be a bug, you are not charged indeed.

    Thanks

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Edited by Marco Zhou Thursday, January 15, 2009 5:10 AM bad typo
    Wednesday, January 14, 2009 7:09 AM
  • The issue with complex binding path is the same as original one: path like "master_detail_Relation.Name" results in creation of new System.Data.RelatedView
    over detail table for each row being binded. If there is another one DataView over detail table - notifies stops working. It's just complicated variant of the original issue, not new one.

    About PSS: It seems that fixing this bug will require BCL patch over technology becoming obsolete. If I couldn't get any results from connect site but closed feedbacks, is there any chance paid support will help me?

    I couldn't understand why ADO.NET guys couldn't answer me quickly and clear as you do?

    Sorry for wasting your time with not yours troubles. Thanks!
    Thursday, January 15, 2009 3:21 AM
  • The same holds true, in the "complex binding path" scenarios, you still have multiple view monitoring a single DataTable as demonstrated in the following simplified example:

    <Window x:Class="DataViewBug.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
      <StackPanel>
        <TextBlock Text="{Binding Path=Value}" DataContext="{Binding Path=SampleTable}"/>
        <TextBlock Text="{Binding Path=Value}" DataContext="{Binding Path=SampleDetailTable/Rel}" x:Name="textBlock"/>
        <Button Width="120" Height="30" Content="Add" x:Name="addButton"/>
      </StackPanel>
    </Window>

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            var dataSet = CreateDataSource();
            this.DataContext = dataSet;
            addButton.Click += delegate
            {
                dataSet.Tables["SampleTable"].Rows[0]["Value"] = (int)(dataSet.Tables["SampleTable"].Rows[0]["Value"]) + 1;
            };
        }

        public DataSet  CreateDataSource()
        {
            var sampleDataSet = new DataSet("SampleDataSet");
            DataTable sampleTable = new DataTable("SampleTable");

            sampleTable.Columns.Add("ID", typeof(int));
            sampleTable.Columns.Add("Value", typeof(int));
            sampleTable.PrimaryKey = new DataColumn[] { sampleTable.Columns[0] };

            sampleDataSet.Tables.Add(sampleTable);

            DataTable sampleDetailTable = new DataTable("SampleDetailTable");

            sampleDetailTable.Columns.Add("ID", typeof(int));
            sampleDetailTable.Columns.Add("DetailedValue", typeof(int));
            sampleDetailTable.PrimaryKey = new DataColumn[] { sampleDetailTable.Columns[0] };

            sampleDataSet.Tables.Add(sampleDetailTable);

            sampleDataSet.Relations.Add("Rel",
              sampleDetailTable.Columns[0],
              sampleTable.Columns[0],
              false);

            sampleDataSet.Tables["SampleDetailTable"].Rows.Add(1, 2);
            sampleDataSet.Tables["SampleTable"].Rows.Add(1, 4);
            return sampleDataSet;
        }
    }

    As we've found out that, this scenario is not supported as I've posted the framework code which causes this behavior.

    I am not clear if this is by design or not, but it looks like that when the source aka DataTable is changed, all the listeners aka DataViews should be notified about this. DataView could be designed to implement independent sorting/filter though.

    Hope this clears things up a little bit.

    -> About PSS: It seems that fixing this bug will require BCL patch over technology becoming obsolete. If I couldn't get any results from connect site but closed feedbacks, is there any chance paid support will help me?

    I think from the customer support service's perspetive, calling PSS is a more direct and formal way to give feedback, and you will get dedicated engineer to work with you on this issue.

    -> Sorry for wasting your time with not yours troubles.
    Thanks for your understanding.

    Thanks

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Thursday, January 15, 2009 8:35 AM
  • Good day for all!

    Marco or anybody else, could you help me contact with ado.net guys?

    I've created same topic at the same time at DataSet section:
    http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/3dda9eee-1a21-44de-9b2c-15f4d29e9ebe

    There's no reaction yet. The bug is still active, there is an robot comment about "escalating this bug to the product unit who works on that specific feature area". No sings of live :)

    I'm still not ready to get paid support without guaranteed chance to get any resul but "sorry, not suported".
    Monday, January 19, 2009 4:42 AM
  • Hi there,

    I know it's been a long time since this response, Will it be possible for you to provide the complex scenario where Dispose is not helping? We want to investigate further if the reason for not updating the view is the same as in the primitive scenarios.

    Thanks!
    Juan
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, November 18, 2009 6:52 PM
  • Hi!

    1) As of .Net 4b2, all samples I've works fine. Thanks for great job!
    >Will it be possible for you to provide the complex scenario where Dispose is not helping?
    2) Oups... It was trivial miswrote: I mean, it's hard to call Dispose on child DataView's (System.Data.RelatedView in reality) as they created implicitely and Dispose over parent DataView doesn't call child's ones.

    See the post starting with

    "The issue with complex binding path is the same as original one: path like "master_detail_Relation.Name" results in creation of new System.Data.RelatedView
    over detail table for each row being binded. If there is another one DataView over detail table - notifies stops working. It's just complicated variant of the original issue, not new one."

    and Marco's reply to it.

    (sorry, could not find a way to copy links to the posts)
    Friday, November 20, 2009 2:55 AM
  • I'd like to add to this... I am using the .NET 4 RC and the bug still exists...   The only way to rebuild the related view is to build the dataview over again and reset the data context.  I've tried every refresh trick I know of...

    This is frustrating since after any save we have to rebind everything in order to get all related views to 'refresh' with the parent's new identity value given from the server.


    Here's a simulation of updating the auto-incrementing ID from the server:

    I have 2 collection view sources:
      <CollectionViewSource x:Key="cvsParentT" />
      <CollectionViewSource x:Key="cvsChildT" Source="{Binding Source={StaticResource cvsParentT}, Path=FK_ParentT_ChildT}" />


    I auto update the identity value with the new one given from the server:
      _data.ParentT.ParentTIDColumn.ReadOnly = false;
      _data.ParentT[0].ParentTID = 25;
      _data.ParentT.ParentTIDColumn.ReadOnly = true;



    The cvsChildT RelatedView is not updated to reflect the new primary key value...  I must do the following in order to 'refresh':
      ((CollectionViewSource)FindResource("cvsParentT")).Source = new DataView(_data.ParentT);


    You may be thinking, "that's not so bad!".  Well it is when we have hundreds of forms that can no longer use the built in methods to bind... We have to roll our own for each form in order to:

    1) Bind to the change event of the primary key
    2) Detect that the change is changing the current row
    3) bind to a new dataview
    4) move the pointer to the new row in the dataview
    -- Or something like the above...

    Or... we're forced to have the client close all windows before saving which is not ideal.  This BUG really does make things difficult for us and makes binding to data much more cumbersome and complicated than the windows forms methods.

    Monday, February 15, 2010 11:47 AM