none
Как правильно очистить Элемент BindingList от связанных через EntitySet данных RRS feed

  • Вопрос

  • Добрый день!

    Есть XAML  в котором приведу только то что касается привязки данных:

    <CollectionViewSource x:Key="uploadBillsViewSource" d:DesignSource="{d:DesignInstance {x:Type local:uploadBill}, CreateList=True}"/>
    

    <Grid DataContext="{Binding Mode=OneWay Source={StaticResource uploadBillsViewSource}}">

    <DataGrid ItemsSource="{Binding Mode=OneWay}" IsSynchronizedWithCurrentItem="True"> <DataGrid ItemsSource="{Binding /invoice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="True"/>

    <DataGrid ItemsSource="{Binding Path=/invoice/invoiceProduct, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

    </Grid>

    Есть

    uploadBills = ((from z in DataContext.uploadBill orderby z.id select z) asIListSource).GetList() asBindingList<uploadBill>;
    uploadBillsViewSource.Source = uploadBills;
      

    В целом все работает, можно вручную ходить по элементам, удалять их и добавлять. Абсолютно все работает во всех трех таблицах.

    Проблемы начинаются при удалении или добавлении из кода.

    Задача очистить вторую и третью таблицу и заполнит их по новой.

    Очистку делаю следующим образом:

            private void ClearInvoice2(uploadBill currentBill)
            {
                foreach (var item in currentBill.invoice)
                    item.invoiceProduct.Clear();
     
                currentBill.invoice.Clear();
            }

    Все это срабатывает и я наблюдаю пустой currentBill, который предварительно выбран в первой таблице

    uploadBill currentBill = (uploadBill)uploadBillDataGrid.SelectedItem;
    ClearInvoice2(currentBill);

    Причем в SQL записи в таблицах Invoce и InvoceProduct полностью удаляются.
    Теперь пытаюсь вставить новый invoce в выбранный uploadBill

    uploadBill currentUploadBill = (uploadBill)uploadBillDataGrid.SelectedItem;

    ...

    foreach (bill_of_lading item in upbill)

    ......

    invoice newinvoice = newinvoice(); newinvoice.customerID = item.order.customerID.Value; newinvoice.date = DateTime.Now; invoiceProduct ip = newinvoiceProduct(); ip.productID = item.order.productID.Value; ip.quantity = item.netto; newinvoice.invoiceProduct.Add(ip); currentUploadBill.invoice.Add(newinvoice); DataContext.SubmitChanges(); uploadBillsViewSource.View.Refresh();

    В результате во второй таблице появляются новые invoce и все хорошо, а третья пустая, ничего не отображает во всех invoсе в currentBill.

    Теперь даже вручную для выбранных новых invoce невозможно добавить invoiceProduct в третью таблицу, точнее добавить можно, но к invoce запись не привязывается. Она как бы сама по себе.

    При этом в SQL все отлично правильно записалось.

    Если просто перезагрузить приложение, то все данные появятся во всех таблицах и их можно будет увидеть.

    Пробовал перезагружать BindingList и ViewSource после удаления и вставки данных и это не помогло, что меня крайне удивило и озадачило.

    uploadBills = ((from z in DataContext.uploadBill orderby z.id select z) asIListSource).GetList() as BindingList<uploadBill>;uploadBillsViewSource.Source = uploadBills;

    Впечатление такое, что отваливается itemsource у третьей таблицы с invoiceProduct. Хотя с элементами которые мы программно не меняли по прежнему все хорошо во всех трех таблицах.

    Странно еще, что со второй никаких проблем нет.

    Прошу помощи, идеи закончились, нервы на пределе.

     




    13 марта 2013 г. 17:59

Ответы

  • Похоже bag все же в связях третьей и второй таблицах, точнее в биндинге.

    Пока вроде заработало таким образом, но уверенности нет уже ни в чем:

    <DataGrid x:Name="productDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Path=SelectedItem.product, ElementName=invoceDataGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="15,2,10,10" IsSynchronizedWithCurrentItem="True" IsReadOnly="True" Grid.Row="2">

    Привязал ItemsSource к выделенному элементу родительской таблицы, вместо /invoce/product.

    Отмечать как решение пока не буду.


    28 марта 2013 г. 13:22

Все ответы

  • Уважаемый пользователь!

    В вашей теме отсутствует активность в течение последних 5 дней. При отсутствии каких-либо действий в течение 2 последующих дней, тема будет переведена в разряд обсуждений. Вы можете возобновить дискуссию, просто оставив сообщение в данной теме

    19 марта 2013 г. 14:28
    Модератор
  • Может тогда лучше в ветку "Работа с данными" переместите?

    20 марта 2013 г. 17:27
  • Может тогда лучше в ветку "Работа с данными" переместите?

    Несомненно. Может я Ваш вопрос не совсем понял, но посмотрите решение предложенное здесь:

    Remove entry of a Bindinglist from a Linq results. - 2 birds in one shot?

    21 марта 2013 г. 9:52
    Модератор
  • Remove(item) работает также как и clear(), только нужно цикл организовывать, просто clear проще и возможно быстрее.

    Дело не  в том, что не правильно удаляются данные из Bindinglist или SQL-базы, а в том что привязка  Path=/invoice/invoiceProduct в третьей таблице работает неправильно.

    Описание проблемы можно прочитать со слов "Теперь даже вручную для выбранных новых invoce невозможно добавить..."  в первом посте.

    Там какой-то кэш видимо не чистится, сейчас не помню чей он, таблицы или CollectionViewSource.

    Может есть другие варианты с удалением данных с entity из коллекций привязанных к таблице?

    22 марта 2013 г. 10:45
  • Все оказалось еще хуже чем я описал выше.

    Проблема с третьей связанной таблицей начинаются даже при "ручном" удалении строк из второй таблицы.

    Создал тестовый проект и выложил на SkyDrive .

    Что это глюк или неправильная запись и обновление изменений?

    PS: описание установки и подробное описание проблемы в файлах txt проекта.

    Весь код ниже. Возможно кто-нибудь сразу скажет в чем проблема этой классической задачи:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApplication40
    {
        /// <summary>
        /// Логика взаимодействия для MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            private BindingList<invoce> invoices;
            private BindingList<journal> journals;
            private BindingList<product> products;
    
            //private ObservableCollection<invoce> invoices;
            //private ObservableCollection<journal> journals;
            //private ObservableCollection<product> products;
    
    
            private CollectionViewSource invoiceViewSource;
            private CollectionViewSource journalViewSource;
            private CollectionViewSource productViewSource;
    
            DataClasses1DataContext DataClassesDataContext = new DataClasses1DataContext();
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded_1(object sender, RoutedEventArgs e)
            {
                journals = ((from z in DataClassesDataContext.journal orderby z.id select z) as IListSource).GetList() as BindingList<journal>;
                invoices = ((from z in DataClassesDataContext.invoce orderby z.id select z) as IListSource).GetList() as BindingList<invoce>;
                products = ((from z in DataClassesDataContext.product orderby z.id select z) as IListSource).GetList() as BindingList<product>;
    
                
                //invoices = new ObservableCollection<invoce>(from z in DataClassesDataContext.invoce orderby z.id select z);
                //journals = new ObservableCollection<journal>(from z in DataClassesDataContext.journal orderby z.id select z);
                //products = new ObservableCollection<product>(from z in DataClassesDataContext.product orderby z.id select z);
    
                journalViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("journalViewSource")));
                invoiceViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("invoceViewSource")));
                productViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("productViewSource")));
                
                journalViewSource.Source = journals;
                invoiceViewSource.Source =  invoices;
                productViewSource.Source = products;
    
            }
    
            private void saveButton_Click(object sender, RoutedEventArgs e)
            {
                DataClassesDataContext.SubmitChanges();
                productViewSource.View.Refresh();
                invoiceViewSource.View.Refresh();
                journalViewSource.View.Refresh();
            }
    
            private void ClearTab(journal currentJournal)
            {
                foreach (var item in currentJournal.invoce)
                    item.product.Clear();
    
                currentJournal.invoce.Clear();
            }
    
            private void clearButton_Click(object sender, RoutedEventArgs e)
            {
                journal currentJournal = journalDataGrid.SelectedItem as journal;
    
                if (currentJournal != null)
                {
                    ClearTab(currentJournal);
                    saveButton_Click(sender, e);
                }
                else
                    MessageBox.Show(" не выбран журнал ");
            }
    
        }
    }


    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication40" mc:Ignorable="d" x:Class="WpfApplication40.MainWindow"
            Title="MainWindow" Height="615" Width="804" Loaded="Window_Loaded_1">
        <Window.Resources>
            <CollectionViewSource x:Key="journalViewSource" d:DesignSource="{d:DesignInstance {x:Type local:journal}, CreateList=True}"/>
        </Window.Resources>
        <Grid DataContext="{StaticResource journalViewSource}">
            <DataGrid x:Name="journalDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True}" Margin="10,10,432,400" RowDetailsVisibilityMode="VisibleWhenSelected" IsSynchronizedWithCurrentItem="True">
                <DataGrid.Columns>
                    <DataGridTemplateColumn x:Name="dateColumn" Header="date" Width="SizeToHeader">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <DatePicker SelectedDate="{Binding date, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn x:Name="idColumn" Binding="{Binding id}" Header="id" Width="SizeToHeader"/>
                </DataGrid.Columns>
            </DataGrid>
            <DataGrid x:Name="invoceDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding /invoce, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Margin="10,190,432,218" RowDetailsVisibilityMode="VisibleWhenSelected" IsSynchronizedWithCurrentItem="True">
                <DataGrid.Columns>
                    <DataGridTemplateColumn x:Name="dateColumn1" Header="date" Width="SizeToHeader">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <DatePicker SelectedDate="{Binding date, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn x:Name="idColumn1" Binding="{Binding id}" Header="id" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="journal_idColumn" Binding="{Binding journal_id}" Header="journal id" Width="SizeToHeader"/>
                </DataGrid.Columns>
            </DataGrid>
            <DataGrid x:Name="productDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding /invoce/product, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Margin="10,372,432,10" RowDetailsVisibilityMode="VisibleWhenSelected" IsSynchronizedWithCurrentItem="True">
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="idColumn2" Binding="{Binding id}" Header="id" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="invoice_idColumn" Binding="{Binding invoice_id}" Header="invoice id" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="nameColumn" Binding="{Binding name}" Header="name" Width="SizeToHeader"/>
                </DataGrid.Columns>
            </DataGrid>
            <Button x:Name="saveButton" Content="Записать" HorizontalAlignment="Left" Margin="480,10,0,0" VerticalAlignment="Top" Width="306" Click="saveButton_Click"/>
            <Button x:Name="clearButton" Content="Очистить" HorizontalAlignment="Left" Margin="480,64,0,0" VerticalAlignment="Top" Width="75" Click="clearButton_Click"/>
    
        </Grid>
    </Window>




    • Изменено serge73 23 марта 2013 г. 8:44
    23 марта 2013 г. 8:33
  • Как оказалось, и удалять-то ничего не нужно, проблемы с третьей таблицей начинаются уже при добавлении новых элементов во вторую и затем в третью.

    Попробовал следующие методы, ничего не помогает.

            private void saveButton_Click(object sender, RoutedEventArgs e)
            {
                DataClassesDataContext.SubmitChanges();
                journals = ((from z in DataClassesDataContext.journal orderby z.id select z) as IListSource).GetList() as BindingList<journal>;
                journalViewSource.View.Refresh();
                productDataGrid.Items.Refresh();
                journals.ResetBindings();
             }

    25 марта 2013 г. 17:11
  • Здравствуйте,

    А когда используете ObservableCollection вместо BindingList, что происходит?

    26 марта 2013 г. 16:10
    Модератор
  • Абсолютно тоже самое. Как видно выше я это попробовал.

    Проблема возможно в классах LINQ2SQL, которые я создаю автоматически стандартным добавлением dbml (MSLinqToSQLGenerator).

    Попробовал еще интерфейс IEditableCollectionView  для всех трех таблиц. Методы добавления и удаления аналогичны нижеописанным.

    Проблема остается - сбой привязки между второй и третьей таблицей.

    Заметил, что удаление происходит для таблиц по разному. В jornal из sql удаляется запись(строка) полностью, а для остальных удаляется соответствующее значение journal_id и invoice_id соответственно, а сама запись (строка) остается.

            private void addInvoceButton(object sender, RoutedEventArgs e)
            {
                IEditableCollectionView editableCollectionView = invoceDataGrid.Items as IEditableCollectionView;
    
                editableCollectionView.AddNew();
                editableCollectionView.CommitNew();
                DataClassesDataContext.SubmitChanges();
            }
    
            private void delInvoceButton(object sender, RoutedEventArgs e)
            {
                IEditableCollectionView editableCollectionView = invoceDataGrid.Items as IEditableCollectionView;
    
                if (invoceDataGrid.SelectedItem != null && invoceDataGrid.SelectedItem.GetType().Name == "invoce")
                {   
                    editableCollectionView.Remove(invoceDataGrid.SelectedItem);
                    DataClassesDataContext.SubmitChanges();
                }
            }

    26 марта 2013 г. 16:45
  • А пробовали открыть dbml Вашей Linq to SQL модели XML Editor'ом и добавить в Association'ах:

    DeleteOnNull = "true"

    Еще можете посмотреть эти темы, вдруг окажутся полезными:

    Advanced Paged Collection View

    Enter PagedCollectionView

    Updating EntitySets with LINQ2SQL

    27 марта 2013 г. 8:53
    Модератор
  • Похоже bag все же в связях третьей и второй таблицах, точнее в биндинге.

    Пока вроде заработало таким образом, но уверенности нет уже ни в чем:

    <DataGrid x:Name="productDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Path=SelectedItem.product, ElementName=invoceDataGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="15,2,10,10" IsSynchronizedWithCurrentItem="True" IsReadOnly="True" Grid.Row="2">

    Привязал ItemsSource к выделенному элементу родительской таблицы, вместо /invoce/product.

    Отмечать как решение пока не буду.


    28 марта 2013 г. 13:22