Datatable vs. bindinglist

I00 bindinglist with datagridview

Basics

Novice developers tend to create a container (database table) that encompasses all there is to know about an object e.g. for a customer, first name, last name, street, city, state, country name. Then in code allow a user to add a new customer by inputting information into TextBox controls for first, last name, street, city and state while country names are presented in a ComboBox or ListBox as an array of string either hard coded which is the norm or have a reference table of country names. If a country name changes this creates a problem as all records in a database table need to be updated.

No matter what the list may be, a list of country names, product names, customer names the better solution is to treat each type with a primary key. For instance, selecting any of these objects from a list into a ComboBox or ListBox the view should be what is intended to allow users to select then beneath have a value which points to a primary key in a database table or reference table.

Binding and ObservableCollection

Binding to an ObjservableCollection is also pretty straightforward. In the sample below we’re changing the value of the Company propety for the first item in the List. When we run the project, you can see that the value is changed on the ListView and we didn’t have to rebind it or do any more coding:

namespace WpfApplication2

{

   /// <summary>

   /// Interaction logic for MainWindow.xaml

   /// </summary>

   public partial class MainWindow : Window

   {

       public MainWindow()

       {

           InitializeComponent();

           ObservableCollection<business> businesses = new ObservableCollection<business>();

           businesses.Add(new Business(«Microsoft», «http://www.microsoft.com», «123-421-1231»));

           businesses.Add(new Business(«SkyXoft», «http://www.skyxoft.com»,»123-321-1231″));

           businesses.Add(new Business(«LicenseSpot», «http://www.licensespot.com», «123-312-3212»));

           BusinessListView.ItemsSource = businesses;

           businesses.Company = «Microsoft Corp»;

       }

   }

   public class Business

   {

       public string Company { get; set; }

       public string Url { get; set; }

       public string Phone { get; set; }

       public Business(string company, string url, string phone)

       {

           this.Company = company;

           this.Url = url;

           this.Phone = phone;

       }

   }

}

</business></business>

Edit Items in ListBox and be seen

Using the same methods above to add items needs additional logic to permit editing items in a ListBox or ComboBox, in this case implementing INotifyPropertyChanged Interface. In code samples provides a slightly different version of implementation is used in most cases by adding JetBrains.Annotations NuGet package. Not interested in JetBrains.Annotations, no problem, using the conventional implementation of  INotifyPropertyChanged works well too, JetBrains simply makes it easier to write change notification for intended properties to work with change notification.

Note, when working with EF Core 5 or higher consider using ObservableCollectionExtensions.ToBindingList which is a language extension that handles notification changes.

The class is different from the above example along with the user interface as in this example focus is on adding new items along with editing existing customers in a single ListBox.

Sample user interface provides adding and editing

Advantages/Disadvantages of different implementations for Comparing Objects

Probably the biggest advantage to accepting a as opposed to an is the ability to write anonymous methods. If I have, let’s say, a , where contains an property that should be used for sorting, I can write:

Which is a lot more convenient than having to write an entire implementation.

I’m not sure that accepting an really has any major advantages, except for compatibility with legacy code (including .NET Framework classes). The property is only really useful for primitive types; everything else usually requires extra work to code against.

To avoid code duplication when I need to work with , one thing I usually do is create a generic comparer, like this:

This allows writing code such as:

It’s not exactly pretty, but it saves some time.

Another useful class I have is this one:

Which you can write code designed for as:

Устранение неполадок

В этом разделе приводятся несколько элементов, которые помогут устранить неполадки приложений привязки данных LINQ to SQL.

  • Необходимо использовать свойства — использования одних полей недостаточно. Это требование обусловлено Windows Forms.

  • По умолчанию , и типы баз данных сопоставляют с массивом байтов. В данном сценарии не поддерживается метод , поэтому эти объекты невозможно отобразить.

  • Член класса, сопоставленный с первичным ключом, имеет метод задания, но LINQ to SQL не поддерживает изменение удостоверения объекта. Поэтому первичный/уникальный ключ, используемый в сопоставлении, не может быть обновлен в базе данных. Изменение в сетке вызывает исключение при вызове SubmitChanges.

  • Если сущность привязана в двух отдельных сетках (например, в основной сетке и в сетке подробных сведений), операция в основной сетке не распространяется на сетку подробных сведений.

Solution 1 — C#

An can be updated from UI exactly like any collection. The true difference is rather straightforward:

implements which provides notification when the collection is changed (you guessed ^^)
It allows the binding engine to update the UI when the is updated.

However, implements .

provides notification on collection changes, but not only that. It provides a whole bunch of functionality which can be used by the UI to provide a lot more things than only UI updates according to changes, like:

  • Sorting
  • Searching
  • Add through factory (AddNew member function).
  • Readonly list (CanEdit property)

All these functionalities are not available in

Another difference is that relays item change notifications when its items implement . If an item raises a event, the will receive it an raises a with and (if an item was replaced, ). doesn’t relay item notifications.

Note that in Silverlight, is not available as an option: You can however use s and (and if I remember well).

BindingList: основные принципы и преимущества

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

Основные принципы работы с BindingList включают:

  1. Создание экземпляра класса BindingList, используя ключевое слово new.
  2. Добавление, удаление и изменение элементов в списке через его методы и свойства.
  3. Привязка элементов управления, таких как DataGridView или ListBox, к BindingList для автоматического обновления данных при изменении списка.

Преимущества использования BindingList:

  • Автоматическое обновление данных: BindingList предоставляет механизм автоматического обновления привязанных элементов при изменении списка. Это избавляет разработчика от необходимости самостоятельно обрабатывать события и принудительно обновлять элементы управления.
  • Удобство использования: Вместо того, чтобы вручную добавлять, удалять или изменять элементы в элементах управления, можно использовать методы и свойства BindingList для выполнения этих операций. Это значительно упрощает работу с данными и уменьшает вероятность ошибок.
  • Поддержка сортировки и фильтрации: BindingList предоставляет ряд методов и свойств для сортировки и фильтрации списка. Это упрощает работу с большими объемами данных и обеспечивает возможность быстрого получения нужных результатов.
  • Интеграция с другими компонентами: BindingList является частью пространства имен System.ComponentModel и легко интегрируется с другими компонентами и функциями платформы .NET.

В заключение, BindingList предоставляет удобный и мощный механизм для работы с списками объектов в C#. Его использование позволяет с легкостью обновлять и управлять данными, а также обеспечивает большую гибкость и функциональность при разработке приложений.

Привязка к свойству внешнего объекта

Предположим, в рамках нашего приложения существует некий слой, который является источником данных для нашего пользовательского интерфейса. Этот слой может быть реализован различным образом — начиная от простого статического класса, заканчивая неким сервисом с публичным контрактом и сложной логикой инстанциации. В любом из этих сценариев мы можем декларативно осуществить привязку к этому объекту.

Возьмем для примера класс , который генерирует Visual Studio при задании каких-либо конфигурационных параметров. Получить экземпляр этого класса с заполненными данными можно получить через публичное статическое свойство :

Далее в этом классе определяются публичные поля, соответствующие настройкам нашего приложения. В демонстрационном примере я создам одну настройку . Таким образом, в составе данного класса появится нужное свойство:

После этого, мы можем, например, императивно обратится к этому свойству и присвоить его значение какому-то элементу управления:

Однако, эту же функциональность можно задать декларативно используя XAML:

Как мы видим, здесь в качестве источника указывается статическое свойство класса, а в параметре указывается имя свойства уже инстанциированного класса. Кроме отображений настроек класса очень удобно пользоваться Bindings для изменения этих настроек, для этого используется режим двунаправленного Binding:

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

Здесь как мы видим используется режим однонаправленного связывания (), т.к. свойство класса предназанчено только для чтения.

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

Тогда привязка к элементу будет выглядеть следующим образом:

Другой сценарий — класс, поставляющий нам данные не имеет статического свойства, поставляющего нам инстанс класса. В этом случае мы можем объявить этот класс в ресурсах, при этом при созданни экземпляра окна будет создан один инстанс такого класса, который будет обслуживать все последующие запросы:

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

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

What is the difference between ObservableCollection and BindingList?

The true difference is rather straightforward: ObservableCollection implements INotifyCollectionChanged which provides notification when the collection is changed (you guessed ^^) It allows the binding engine to update the UI when the ObservableCollection is updated. However, BindingList implements IBindingList .

What is an ObservableCollection?

An ObservableCollection is a dynamic collection of objects of a given type. Objects can be added, removed or be updated with an automatic notification of actions. When an object is added to or removed from an observable collection, the UI is automatically updated.

What is BindingList in C#?

A BindingList<> is a wrapper around a typed list or a collection, which implements the IBindingList interface. This is one of the standard interfaces that support two-way databinding. It works by implementing the ListChanged event, which is raised when you add, remove, or set items.

What is the use of ObservableCollection in WPF?

ObservableCollection is a collection that allows code outside the collection be aware of when changes to the collection (add, move, remove) occur. It is used heavily in WPF and Silverlight but its use is not limited to there.

How do you bind a list?

Following are some simple steps to bind your listbox/dropdown list to List.

  1. Create a List in you code behind file i.e. . CS file. Following code shows how the List of string is created.
  2. After creating List, bind List with your listbox/dropdown list. The following code binds to dropdown and listbox too.

Add items to ListBox and be visible

Provide an interface to move customers from one ListBox to another ListBox.
Data is read from a SQL-Server database using the following class which returns a list of customers. Take the list and assign to the left ListBox then setup the right ListBox as a new list of customer followed by writing code for the buttons which are responsible for taking a selected customer and moving to the opposite ListBox using conventional code e.g. cast the SelectedItem to a Customer to a variable, add to the other ListBox and delete from the current ListBox. Unfortunately nothing appears in the opposite ListBox while the current ListBox selected item is removed. Many developers have tried to figure this out and failed simply because there is a lack of understanding how things work, it works with a DataGridView why not a ListBox or ComboBox? Simply answer, a DataGridView was designed to work with data while neither the ListBox or ComboBox were but can with proper understanding.

Another attempt may be to use two BindingSource components as the DataSource for each ListBox, this will fail but with a simple reset of the BindingSource can be forced to show newly added items e.g. SomeBindingSource.ResetBindings. This means the current selected item is lost from the reset.

The final attempt, and proper method is to use a BindingList of Customer.

Customer class

Form code
Both ListBox controls use a BindingList<Customer> which a ListBox will reflect adding new items.

The above resolves how to update a ListBox or ComboBox when new items are added.

List T vs BindingList T Advantages/DisAdvantages

A is simply an automatically resizing array, of items of a given type, with a couple of helper functions (eg: sort). It’s just the data, and you’re likely to use it to run operations on a set of objects in your model.

A is a wrapper around a typed list or a collection, which implements the interface. This is one of the standard interfaces that support two-way databinding. It works by implementing the event, which is raised when you add, remove, or set items. Bound controls listen to this event in order to know when to refresh their display.

When you set a BindingSource’s DataSource to a , it internally creates a to wrap your list. You may want to pre-wrap your list with a yourself if you want to access it outside of the BindingSource, but otherwise it’s just the same. You can also inherit from to implement special behavior when changing items.

is handled by the BindingSource. It’ll call BeginEdit on any implementing object when you change the data in any bound control. You can then call EndEdit/CancelEdit on the BindingSource and it will pass it along to your object. Moving to a different row will call EndEdit as well.

Привязка к методу внешнего объекта

Хорошо, со свойствами разобрались. Однако, очень часто бывает так, что данные нам передаются не через свойства, а посредством вызова методов. В этом случае все сложнее, не не на много :).

Для того, чтобы определить связь с данными, возвращаемыми методом существует объект . Он позволяет указать класс, в котором содержится метод, инстанциировать его если нужно и вызвать метод. Например у нас существует класс, в котором определен метод, возвращающий данные:

Для того, чтобы получить возможность определения Binding на основе такого класса в XAML-коде необходимо определить и указать в нем имя класса и имя вызываемого метода:

После этого, можно ссылаться на в качестве источника:

Точно также в качестве результата работы метода можно вернуть не просто какой-то простой тип, но и объект или коллекцию:

И создать привязку к ним:

Ну и наконец мы можем передавать значения параметров методов, если метод содержит параметры. Для этого мы можем использовать коллекцию объекта :

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

UPDATE (спасибо Виталию Дильмухаметову):Если в качестве параметра нужно передать тип (), это можно сделать так:

При этом вызываемый метод может выглядеть следующим образом:

Тогда в качестве значения параметра будет передано .

Таким образом, мы видим, что имеем возможность получить доступ к данным, которые представлены через вызов методов класса.

Такие вот преимущества мы получаем используя подход декларативного связывания данных, который появился в WPF. В противовес этому, при использовании WinForms нам предлагается написать много императивного кода, особенно когда нужно реализовать сценарий двунаправленного связывания. Понятно как это скажется на читаемости кода и поддержке/развитии приложения. :)

Преимущества использования BindingList

BindingList — это класс в пространстве имен System.ComponentModel, который представляет собой обертку над обычным списком объектов и позволяет автоматически обновлять пользовательский интерфейс при изменении данных в списке.

Преимущества использования BindingList включают:

  1. Автоматическое обновление пользовательского интерфейса: BindingList поддерживает события, которые позволяют автоматически обновлять пользовательский интерфейс при добавлении, удалении или изменении элементов в списке. Это особенно полезно в случае использования элементов управления, таких как DataGridView или ListBox, которые могут быть привязаны к BindingList.
  2. Отслеживание изменений: BindingList предоставляет возможность отслеживать изменения в списке. Это позволяет легко определить, когда элемент был добавлен, удален или изменен, и выполнить соответствующие действия. Например, можно реагировать на изменение элемента списка, обновлять данные в базе данных или синхронизировать список с другими источниками данных.
  3. Поддержка сортировки и фильтрации: BindingList имеет встроенную поддержку сортировки и фильтрации данных. Это позволяет отображать данные в отсортированном порядке или применять фильтр к элементам списка на основе заданных критериев.
  4. Легкость использования вместе с элементами управления: BindingList может быть легко связан с элементами управления, такими как DataGridView или ListBox, что упрощает отображение и управление данными в пользовательском интерфейсе. Благодаря автоматическому обновлению интерфейса и возможности отслеживания изменений, пользовательский интерфейс всегда будет отражать актуальное состояние списка.
  5. Масштабируемость: BindingList может содержать любое количество элементов и поддерживает расширение списка в процессе выполнения программы. Это делает BindingList очень гибким и масштабируемым решением для работы с коллекциями данных.

В целом, использование BindingList в C# позволяет значительно упростить работу с коллекцией данных, обеспечивая автоматическое обновление пользовательского интерфейса, отслеживание изменений, сортировку и фильтрацию данных.

2 ответа

3

Лучший ответ

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

Если вы используете обычную коллекцию в качестве источника данных, изменения, которые вы делаете через другие связанные с данными элементы управления (или через BindingSource), будут по-прежнему отражаться, но изменения в базовой коллекции напрямую не будут.

13 янв. 2011, в 02:09
Поделиться

10

Связывание с даст вам только одностороннюю привязку; изменения в списке или элементы списка не будут отображаться в . Вы можете использовать или , чтобы получить эту функциональность, но ваш класс по-прежнему должен поддерживать , иначе вы получите только синхронизацию, когда элементы будут добавлены/удалены в/из списка, а не при изменении самих элементов списка.

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

13 янв. 2011, в 01:34
Поделиться

Ещё вопросы

  • SQLSTATE : общая ошибка: 1364 Поле ‘name’ не имеет значения по умолчанию laravel 5.5
  • Как сделать так, чтобы моя программа принимала несколько слов
  • Переменная как ключ массива — выбрано выпадающее меню Yii
  • Определить круги с кругами
  • Символ PortAudio не найден: _PaMacCore_SetupChannelMap на Mountain Lion
  • Изменение непрозрачности Javascript
  • JQuery position.top () медленный с большим количеством элементов
  • нг-если внутри нг-повтор не обновляется с контроллера
  • Удаление файла из папки
  • Как заявление с OR и Inner присоединиться к MySQL
  • C ++: Разница между аргументами и параметрами?
  • Angularjs: элементы массива Sum для диаграмм
  • Перебирать разные типы коллекций в классе
  • Visual Studio c ++ 2012 и вопросы о шейдерах
  • 1Иметь представление обтекания содержимого, но соответствовать родительскому, если есть свободное место
  • Как я могу обновить запись так же, как и другую запись в той же таблице?
  • Что будет делать MySQL, если он обновляется одновременно
  • Сбор продукта и фильтр Magento
  • 1C # Закрывающий обработчик событий не работает
  • isset не работает при отправке формы (на самом деле проблема с БД)
  • 1Не удается изменить InnerHTML класса span?
  • Показать результаты SQL-запроса на основе количества
  • 1В чем разница между двумя способами назначения методов для объекта делегата
  • Разбор XML-кода через PHP в jQuery — Ошибка XML
  • 1Как получить строку текста, которая находится между двумя ‘{‘ круглыми скобками ‘}’, установленными с помощью .NET?
  • 1Как сделать новый сервлет с помощью мастера?
  • 1Определите метод с универсальным параметром типа M <T> в C #
  • Обновление jQuery 1.7.1
  • 1Секунда весны: перехватить URL-адрес легко обойти?
  • MySQL запрос поиска в левом соединении, которые имеют условие, связанное со столбцом
  • Получить последнее значение переменной для цикла
  • Наложение CSS не работает
  • 1Javascript отображаемое имя div
  • Функция вызывается, когда пользователь перестает печатать на клавиатуре
  • ASP.net MVC Можете ли вы перегрузить HttpPost Index ()?
  • 1Если Элемент не существует
  • Стандартный метод обработки не найденных (404) ошибок во всех видах веб-серверов
  • & Амп; в & в base64 + Javascript
  • Директива AngularJS — Как я могу сказать, что выражение атрибута полностью оценено?
  • 1Поиск слова в списке
  • Как мне явно выполнять задачи?
  • Использование IsWow64Process вместо отдельной компиляции
  • 1Регулярное выражение, чтобы соответствовать только когда определенные символы следуют за строкой
  • Вставка записей в первичные столбцы внешнего ключа из другой таблицы
  • 1Проблемы с акцентами в Java во время выполнения
  • Вставьте, если существует
  • Жасмин — модульное тестирование директивы: получение undefined не является объектом
  • Почему $ _POST не распознает определенные загруженные файлы?
  • 1Получить имена всех файлов в пути
  • 1лямбда-выражения для сравнения, содержит ли строка [] заданную строку

Immutable Collections

Immutable (неизменяемые) коллекции не включены в библиотеку базовых классов. Чтобы использовать их в проекте должен быть установлен пакет NuGet System.Collections.Immutable.

Они используют другой подход к созданию коллекций поточно-ориентированных. Вместо использования синхронизирующих блокировок, как это делают параллельные коллекции, неизменяемые коллекции не могут быть изменены после их создания. Это автоматически делает их безопасными для использования в многопоточных сценариях, поскольку другой поток не может изменить их и сделать состояние несовместимым.

Это фундаментальное проектное решение влияет на API классов неизменяемой коллекции. У них даже нет общественных конструкторов. Есть два других способа создать новый экземпляр:

Обычную коллекцию можно преобразовать в неизменяемую, используя метод расширения:

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

Все операции, которые обычно изменяют коллекцию, возвращают новый экземпляр

Важно помнить, что возвращаемое значение должно использоваться вместо исходного экземпляра:. То, что каждый метод возвращает новый экземпляр одного и того же класса, облегчает объединение нескольких вызовов методов:

То, что каждый метод возвращает новый экземпляр одного и того же класса, облегчает объединение нескольких вызовов методов:

Однако такого подхода следует избегать всякий раз, когда это возможно, потому что каждый вызов метода в такой цепочке создает новый экземпляр коллекции. Хотя неизменяемые коллекции реализованы таким образом, чтобы при создании нового экземпляра можно было использовать как можно больше исходной коллекции, некоторые выделения памяти все еще требуются. Это означает больше работы для сборщика мусора.

Лучший способ минимизировать эту проблему — использовать методы, которые могут выполнить необходимые изменения за один вызов. Приведенную выше цепочку вызовов методов можно заменить, например, следующим единственным вызовом метода:

К сожелению специализированные методы не доступны для всех типов сложных модификаций. Например, нет единого метода, доступного для добавления и удаления определенных элементов, как показано ниже:

В таких случаях вместо этого может использоваться Builder:

Метод ToBuilder создаст builder для неизменяемой коллекции, который будет реализовывать интерфейс соответствующей изменяемой коллекции. Его внутренняя структура памяти будет по-прежнему соответствовать одной неизменной коллекции, но операции изменят один и тот же экземпляр, вместо того, чтобы всегда создавать новый. Только при вызове метода ToImmutable экземпляр будет снова имутабельным. Это позволит максимально сократить объем работы сборщика мусора.

Итак, когда следует использовать Immutable коллекции вместо обычных или Concurrent коллекций?

Типичным случаем использования являются многопоточные приложения, особенно когда поток не должен иметь доступ к последнему состоянию коллекции и может использовать потенциально устаревший неизменный экземпляр, который был первоначально передан ему. В этом случае неизменяемые коллекции могут обеспечивать более высокую производительность, несмотря на дополнительную работу для сборщика мусора, поскольку не требуются блокировки синхронизации.

Если приложению необходимо отменить операции над коллекциями, может иметь смысл использовать неизменяемые коллекции даже в однопоточных сценариях. Снимки предыдущих состояний являются побочным продуктом неизменяемых коллекций и не требуют дополнительных ресурсов для создания. Они могут, например, храниться в стеке, чтобы отменить последнее изменение:

Мало того, что создание копий занимает много времени, копии также требуют больше памяти, чем их неизменные аналоги. Копии изменяемых коллекций не разделяют память между ними, в отличие от неизменяемых коллекций, которые часто делятся большими частями, когда они были созданы с помощью модификаций.

Итоги

Выбирая коллекцию для использования в своем коде, всегда начинайте с размышлений о том, какие операции вам нужно будет выполнить с этой коллекцией. Исходя из этого, вы можете выбрать наиболее подходящий интерфейс коллекции.

Если у вас нет каких-либо особых требований, используйте реализацию из пространства имен System.Collections.Generic. Если вы пишете многопоточное приложение и вам нужно изменить коллекцию из нескольких потоков, выберите вместо этого параллельную реализацию одного и того же интерфейса. Рассмотрите имутабельные коллекции, если их поведение и производительность лучше всего соответствуют вашим требованиям.

Понравилась статья? Поделиться с друзьями:
Опытный компьютерщик
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: