Приклади коду з урахуванням особливостей C# 9 і C# 10
1 Обробка даних про книги на книжковій полиці (лабораторна робота № 1)
Єдине істотне доповнення, пов'язане з перевіркою потенційно можливого значення null
, доцільно зробити в інструкції, в якій рядок вводиться з клавіатури. Замість інструкції
string sequence = Console.ReadLine();
слід розташувати таку:
string sequence = Console.ReadLine() ?? "";
Це унеможливить присвоєння змінній sequence значення null
.
2 Ієрархія книжкових полиць (лабораторна робота № 2)
З урахуванням особливостей C# 9 і C# 10 можна модифікувати код програми в такий спосіб:
using System; namespace LabSecond { // Структура для опису автора public struct Author { public string Surname, Name; //Перевизначення еквівалентності public override bool Equals(object? obj) { if (obj == null) { return false; } Author author = (Author)obj; return author.Surname == Surname && author.Name == Name; } // Визначення представлення у вигляді рядку: public override string ToString() { return Name + " " + Surname; } // Визначається у парі з Equals() public override int GetHashCode() { return base.GetHashCode(); } public static bool operator ==(Author left, Author right) { return left.Equals(right); } public static bool operator !=(Author left, Author right) { return !(left == right); } } // Книжка public class Book { public string Title { get; set; } public int Year { get; set; } public Author[] Authors { get; set; } // Конструктор public Book(string title, int year, params Author[] authors) { Title = title; Year = year; Authors = authors; } // Визначення представлення у вигляді рядку // string.Format() забезпечує форматування, аналогічне Console.WriteLine() public override string ToString() { string s = string.Format("Назва: \"{0}\". Рiк видання: {1}", Title, Year); s += "\n" + " Автор(и):"; for (int i = 0; i < Authors.Length; i++) { s += string.Format(" {0}", Authors[i]); if (i < Authors.Length - 1) { s += ","; } else { s += "\n"; } } return s; } // Перевизначення еквівалентності public override bool Equals(object? obj) { if (obj is Book b) { if (b.Authors.Length != Authors.Length) { return false; } for (int i = 0; i < Authors.Length; i++) { if (!b.Authors[i].Equals(Authors[i])) { return false; } } return b.Title == Title && b.Year == Year; } return false; } // Визначається у парі з Equals() public override int GetHashCode() { return base.GetHashCode(); } } // Книжкова полиця public class Bookshelf { public Book[] Books { get; set; } // Конструктор public Bookshelf(params Book[] books) { Books = books; } // Індексатор public Book this[int index] { get { return Books[index]; } set { Books[index] = value; } } // Визначення представлення у вигляді рядку public override string ToString() { string result = ""; foreach (Book book in Books) { result += book; } return result; } // Пошук книжки з певною послідовністю літер public Book[] ContainsCharacters(string characters) { Book[] found = Array.Empty<Book>(); foreach (Book book in Books) { if (book.Title.Contains(characters)) { // Додаємо новий елемент до масиву: Array.Resize(ref found, found.Length + 1); found[^1] = book; } } return found; } // Додавання книжки public void Add(Book book) { Book[] books = Books; Array.Resize(ref books, Books.Length + 1); Books = books; Books[^1] = book; } // Видалення книжки зі вказаними даними public void Remove(Book book) { int i, k; Book[] newBooks = new Book[Books.Length]; for (i = 0, k = 0; i < Books.Length; i++, k++) { if (Books[i].Equals(book)) { k--; } else { newBooks[k] = Books[i]; } } if (i > k) { Array.Resize(ref newBooks, Books.Length - 1); } Books = newBooks; } // Перевантажений оператор додавання книжки public static Bookshelf operator +(Bookshelf bookshelf, Book book) { Bookshelf newBookshelf = new(bookshelf.Books); newBookshelf.Add(book); return newBookshelf; } // Перевантажений оператор видалення книжки public static Bookshelf operator -(Bookshelf bookshelf, Book book) { Bookshelf newBookshelf = new(bookshelf.Books); newBookshelf.Remove(book); return newBookshelf; } } // Книжкова полиця з назвою public class TitledBookshelf : Bookshelf { public string Title { get; set; } public TitledBookshelf(string title, params Book[] books) : base(books) { Title = title; } // Визначення представлення у вигляді рядку public override string ToString() { return Title + "\n" + base.ToString(); } // Перевантажений оператор додавання книжки public static TitledBookshelf operator +(TitledBookshelf titled, Book book) { TitledBookshelf newBookshelf = new(titled.Title, titled.Books); newBookshelf.Add(book); return newBookshelf; } // Перевантажений оператор видалення книжки public static TitledBookshelf operator -(TitledBookshelf titled, Book book) { TitledBookshelf newBookshelf = new(titled.Title, titled.Books); newBookshelf.Remove(book); return newBookshelf; } } class Program { static void Main() { // Створюємо порожню полицю: Bookshelf bookshelf = new(); // Додаємо книжки bookshelf += new Book("The UML User Guide", 1999, new Author() { Name = "Grady", Surname = "Booch" }, new Author() { Name = "James", Surname = "Rumbaugh" }, new Author() { Name = "Ivar", Surname = "Jacobson" }); bookshelf += new Book(@"Об'єктно-орiєнтоване моделювання програмних систем", 2007, new Author() { Name = "Iгор", Surname = "Дудзяний" }); bookshelf += new Book("Thinking in Java", 2005, new Author() { Name = "Bruce", Surname = "Eckel" }); // Виводимо дані на екран: Console.WriteLine(bookshelf); Console.WriteLine(); // Шукаємо книжки з певною послідовністю літер: Console.WriteLine("Уведiть послiдовнiсть лiтер:"); string sequence = Console.ReadLine() ?? ""; Bookshelf newBookshelf = new(bookshelf.ContainsCharacters(sequence)); // Виводимо результат на екран: Console.WriteLine("Знайденi книжки:"); Console.WriteLine(newBookshelf); Console.WriteLine(); // Видаляємо книжку про Java Book javaBook = bookshelf[2]; // індексатор bookshelf -= javaBook; Console.WriteLine("Пiсля видалення книжки:"); Console.WriteLine(bookshelf); Console.WriteLine(); // Створюємо нову полицю TitledBookshelf titledBookshelf = new("Java"); titledBookshelf += javaBook; Console.WriteLine("Нова полиця:"); Console.WriteLine(titledBookshelf); } } }
У коді застосовано механізм зіставлення зі зразком, додатковий контроль null-сумісних типів, нові можливості створення нових об'єктів new
()
, перевантаження операцій ==
та !=
, а також механізм отримання індексів через використання типу Index
.
3 Створення ієрархії узагальнених класів (лабораторна робота № 3)
У прикладі цієї лабораторної роботи окремо створюється бібліотека класів і консольний застосунок. У бібліотеці класів розташовуємо такий код:
using System; using System.Collections.Generic; using System.Xml.Serialization; using System.IO; namespace BookshelfLib { // Структура для опису автора public struct Author { [System.Xml.Serialization.XmlAttributeAttribute()] public string Surname { get; set; } [System.Xml.Serialization.XmlAttributeAttribute()] public string Name { get; set; } // Перевизначення еквівалентності public override bool Equals(object? obj) { if (obj == null) { return false; } Author author = (Author)obj; return author.Surname == Surname && author.Name == Name; } // Визначення представлення у вигляді рядку: public override string ToString() { return Name + " " + Surname; } // Визначається у парі з Equals() public override int GetHashCode() { return base.GetHashCode(); } public static bool operator ==(Author left, Author right) { return left.Equals(right); } public static bool operator !=(Author left, Author right) { return !(left == right); } } // Книжка public class Book<TAuthor> { [System.Xml.Serialization.XmlAttributeAttribute()] public string Title { get; set; } [System.Xml.Serialization.XmlAttributeAttribute()] public int Year { get; set; } public List<TAuthor> Authors { get; set; } // Конструктори public Book() { Title = ""; Authors = new List<TAuthor>(); } public Book(string title, int year, params TAuthor[] authors) { Title = title; Year = year; Authors = new List<TAuthor>(authors); } // Визначення представлення у вигляді рядку override public string ToString() { string s = string.Format("Назва: \"{0}\". Рiк видання: {1}", Title, Year); s += "\n" + " Автор(и):"; for (int i = 0; i < Authors.Count; i++) { s += string.Format(" {0}", Authors[i]); if (i < Authors.Count - 1) { s += ","; } else { s += "\n"; } } return s; } // Перевизначення еквівалентності public override bool Equals(object? obj) { if (obj is Book<TAuthor> b) { if (b.Authors.Count != Authors.Count) { return false; } for (int i = 0; i < Authors.Count; i++) { if (!b.Authors[i].Equals(Authors[i])) { return false; } } return b.Title == Title && b.Year == Year; } return false; } // Визначається у парі з Equals() public override int GetHashCode() { return base.GetHashCode(); } } // Книжкова полиця public class Bookshelf<TAuthor> { public List<Book<TAuthor>> Books { get; set; } // Конструктор public Bookshelf(params Book<TAuthor>[] books) { Books = new List<Book<TAuthor>>(books); } // Індексатор public Book<TAuthor> this[int index] { get { return Books[index]; } set { Books[index] = value; } } // Визначення представлення у вигляді рядку override public string ToString() { string result = ""; foreach (Book<TAuthor> book in Books) { result += book; } return result; } // Пошук книжки з певною послідовністю літер public List<Book<TAuthor>> ContainsCharacters(string characters) { List<Book<TAuthor>> found = new(); foreach (Book<TAuthor> book in Books) { if (book.Title.Contains(characters)) { // Додаємо новий елемент до списку: found.Add(book); } } return found; } // Додавання книжки public void Add(Book<TAuthor> book) { Books.Add(book); } // Видалення книжки зі вказаними даними public void Remove(Book<TAuthor> book) { Books.Remove(book); } // Читання книжок за допомогою механізму десеріалізації public bool ReadBooks(string fileName) { XmlSerializer deserializer = new(typeof(List<Book<TAuthor>>)); using TextReader textReader = new StreamReader(fileName); var data = deserializer.Deserialize(textReader); if (data == null) { return false; } Books = (List<Book<TAuthor>>)data; return true; } // Запис книжок за допомогою механізму серіалізації public void WriteBooks(string fileName) { XmlSerializer serializer = new(typeof(List<Book<TAuthor>>)); using TextWriter textWriter = new StreamWriter(fileName); serializer.Serialize(textWriter, Books); } // Вкладений клас для порівняння книжок за алфавітом назв class CompareByTitle : IComparer<Book<TAuthor>> { public int Compare(Book<TAuthor>? b1, Book<TAuthor>? b2) { if (b1 == null || b2 == null) { return 0; } return string.Compare(b1.Title, b2.Title); } } // Вкладений клас для порівняння книжок за кількістю авторів class CompareByAuthorsCount : IComparer<Book<TAuthor>> { public int Compare(Book<TAuthor>? b1, Book<TAuthor>? b2) { if (b1 == null || b2 == null) { return 0; } return b1.Authors.Count < b2.Authors.Count ? -1 : (b1.Authors.Count == b2.Authors.Count ? 0 : 1); } } // Сортування книжок за алфавітом назв public void SortByTitle() { Books.Sort(new CompareByTitle()); } // Сортування книжок за кількістю авторів public void SortByAuthorsCount() { Books.Sort(new CompareByAuthorsCount()); } // Перевантажений оператор додавання книжки public static Bookshelf<TAuthor> operator +(Bookshelf<TAuthor> bookshelf, Book<TAuthor> book) { Bookshelf<TAuthor> newShelf = new() { Books = bookshelf.Books }; newShelf.Add(book); return newShelf; } // Перевантажений оператор видалення книжки public static Bookshelf<TAuthor> operator -(Bookshelf<TAuthor> bookshelf, Book<TAuthor> book) { Bookshelf<TAuthor> newShelf = new() { Books = bookshelf.Books }; newShelf.Remove(book); return newShelf; } } // Книжкова полиця з назвою public class TitledBookshelf<TAuthor> : Bookshelf<TAuthor> { public string Title { get; set; } // Конструктор з параметрами public TitledBookshelf(string title, params Book<TAuthor>[] books) : base(books) { Title = title; } // Визначення представлення у вигляді рядку override public string ToString() { return Title + "\n" + base.ToString(); } // Перевантажений оператор додавання книжки public static TitledBookshelf<TAuthor> operator +(TitledBookshelf<TAuthor> titled, Book<TAuthor> book) { TitledBookshelf<TAuthor> newShelf = new(titled.Title) { Books = titled.Books }; newShelf.Add(book); return newShelf; } // Перевантажений оператор видалення книжки public static TitledBookshelf<TAuthor> operator -(TitledBookshelf<TAuthor> titled, Book<TAuthor> book) { TitledBookshelf<TAuthor> newShelf = new(titled.Title) { Books = titled.Books }; newShelf.Remove(book); return newShelf; } } }
Код класу, який представляє консольний застосунок, буде таким:
using BookshelfLib; namespace BookshelfApp { class Program { static void Main() { // Створюємо порожню полицю: Bookshelf<Author> bookshelf = new(); // Додаємо книжки bookshelf += new Book<Author>("The UML User Guide", 1999, new Author() { Name = "Grady", Surname = "Booch" }, new Author() { Name = "James", Surname = "Rumbaugh" }, new Author() { Name = "Ivar", Surname = "Jacobson" }); bookshelf += new Book<Author>(@"Об'єктно-орiєнтоване моделювання програмних систем", 2007, new Author() { Name = "Iгор", Surname = "Дудзяний" }); bookshelf += new Book<Author>("Thinking in Java", 2005, new Author() { Name = "Bruce", Surname = "Eckel" }); // Виводимо дані на екран: Console.WriteLine(bookshelf); Console.WriteLine(); // Шукаємо книжки з певною послідовністю літер: Console.WriteLine("Уведiть послiдовнiсть лiтер:"); string sequence = Console.ReadLine() ?? ""; Bookshelf<Author> newBookshelf = new() { Books = bookshelf.ContainsCharacters(sequence) }; // Виводимо результат на екран: Console.WriteLine("Знайденi книжки:"); Console.WriteLine(newBookshelf); Console.WriteLine(); try { // Зберігаємо дані про книжки: bookshelf.WriteBooks("Bookshelf.xml"); // Здійснюємо сортування за назвами та зберігаємо у файлі: bookshelf.SortByTitle(); Console.WriteLine("За назвами:"); Console.WriteLine(bookshelf); Console.WriteLine(); bookshelf.WriteBooks("ByTitle.xml"); // Здійснюємо сортування за кількістю авторів та зберігаємо у файлі: bookshelf.SortByAuthorsCount(); Console.WriteLine("За кiлькiстю авторiв:"); Console.WriteLine(bookshelf); Console.WriteLine(); bookshelf.WriteBooks("ByAuthorsCount.xml"); // Відтворюємо першу полицю в початковому варіанті bookshelf.ReadBooks("Bookshelf.xml"); Console.WriteLine("Початковий стан:"); Console.WriteLine(bookshelf); Console.WriteLine(); // Видаляємо книжку про Java Book<Author> javaBook = bookshelf[2]; // індексатор bookshelf -= javaBook; Console.WriteLine("Пiсля видалення книжки:"); Console.WriteLine(bookshelf); Console.WriteLine(); // Створюємо нову полицю. Для зберігання даних про автора використовуємо рядок TitledBookshelf<string> titledBookshelf = new("Java"); titledBookshelf += new Book<string>("Thinking in Java", 2005, "Bruce Eckel"); Console.WriteLine("Полиця з книжками з мови Java:"); Console.WriteLine(titledBookshelf); titledBookshelf.WriteBooks("JavaBooks.xml"); } catch (Exception ex) { Console.WriteLine("------------Виняток:------------"); Console.WriteLine(ex.GetType()); Console.WriteLine("-------------Змсiт:-------------"); Console.WriteLine(ex.Message); Console.WriteLine("-------Трасування стеку:-------"); Console.WriteLine(ex.StackTrace); } } } }
Як і в коді попередньої роботи, застосовано механізм зіставлення зі зразком, додатковий контроль null-сумісних типів, нові можливості створення нових об'єктів new
()
, перевантаження операцій ==
та !=
для типів-значень. Також видалені зайві using
-директиви.
4 Створення GUI-застосунку для обробки даних про книжки (лабораторна робота № 4)
У прикладі цієї лабораторної роботи доповнюється бібліотека класів. Сирцевий код класу BookshelfWithLINQ
буде таким:
// BookshelfWithLINQ.cs namespace BookshelfLib { public class BookshelfWithLINQ<TAuthor> : Bookshelf<TAuthor> { // Конструктор public BookshelfWithLINQ(params Book<TAuthor>[] books) : base(books) { } public new List<Book<TAuthor>> ContainsCharacters(string characters) { var found = from book in Books where book.Title.Contains(characters) select book; // повертаємо результат пошуку found, // створивши на його основі новий список типу List<Book<TAuthor>> // для забезпечення відповідності типів: return new List<Book<TAuthor>>(found); } // Сортування за алфавітом назв: public new void SortByTitle() { Books = new List<Book<TAuthor>>( from book in Books orderby book.Title select book); } // Сортування за кількістю авторів: public new void SortByAuthorsCount() { Books = new List<Book<TAuthor>>( from book in Books orderby book.Authors.Count select book); } // Перевантажений оператор додавання книжки public static BookshelfWithLINQ<TAuthor> operator + (BookshelfWithLINQ<TAuthor> bookshelf, Book<TAuthor> newBook) { var newBooks = new List<Book<TAuthor>>(bookshelf.Books) { newBook }; return new BookshelfWithLINQ<TAuthor>() { Books = newBooks }; } // Перевантажений оператор видалення книжки. // Використання LINQ – суто ілюстративне public static BookshelfWithLINQ<TAuthor> operator - (BookshelfWithLINQ<TAuthor> bookshelf, Book<TAuthor> oldBook) { var newBooks = new List<Book<TAuthor>>( from book in bookshelf.Books where !book.Equals(oldBook) select book); return new BookshelfWithLINQ<TAuthor>() { Books = newBooks }; } } }
Відповідний консольний застосунок:
using BookshelfLib; namespace BookshelfWithLINQApp { class Program { static void Main() { // Створюємо порожню полицю: BookshelfWithLINQ<Author> bookshelf = new(); // Додаємо книжки bookshelf += new Book<Author>("The UML User Guide", 1999, new Author() { Name = "Grady", Surname = "Booch" }, new Author() { Name = "James", Surname = "Rumbaugh" }, new Author() { Name = "Ivar", Surname = "Jacobson" }); bookshelf += new Book<Author>(@"Об'єктно-орiєнтоване моделювання програмних систем", 2007, new Author() { Name = "Iгор", Surname = "Дудзяний" }); bookshelf += new Book<Author>("Thinking in Java", 2005, new Author() { Name = "Bruce", Surname = "Eckel" }); // Виводимо дані на екран: Console.WriteLine(bookshelf); Console.WriteLine(); // Шукаємо книжки з певною послідовністю літер: Console.WriteLine("Уведiть послiдовнiсть лiтер:"); string sequence = Console.ReadLine() ?? ""; BookshelfWithLINQ<Author> newBookshelf = new() { Books = bookshelf.ContainsCharacters(sequence) }; // Виводимо результат на екран: Console.WriteLine("Знайденi книжки:"); Console.WriteLine(newBookshelf); Console.WriteLine(); try { // Зберігаємо дані про книжки: bookshelf.WriteBooks("Bookshelf.xml"); // Здійснюємо сортування за назвами та зберігаємо у файлі: bookshelf.SortByTitle(); Console.WriteLine("За назвами:"); Console.WriteLine(bookshelf); Console.WriteLine(); bookshelf.WriteBooks("ByTitle.xml"); // Здійснюємо сортування за кількістю авторів та зберігаємо у файлі: bookshelf.SortByAuthorsCount(); Console.WriteLine("За кiлькiстю авторiв:"); Console.WriteLine(bookshelf); Console.WriteLine(); bookshelf.WriteBooks("ByAuthorsCount.xml"); // Створюємо нову полицю. Для зберігання даних про автора використовуємо рядок TitledBookshelf<string> titledBookshelf = new("Java"); titledBookshelf += new Book<string>("Thinking in Java", 2005, "Bruce Eckel"); Console.WriteLine("Полиця з книжками з мови Java:"); Console.WriteLine(titledBookshelf); titledBookshelf.WriteBooks("JavaBooks.xml"); // Відтворюємо першу полицю в початковому варіанті bookshelf.ReadBooks("Bookshelf.xml"); Console.WriteLine("Початковий стан:"); Console.WriteLine(bookshelf); Console.WriteLine(); // Видаляємо книжку про Java Book<Author> javaBook = bookshelf[2]; // індексатор bookshelf -= javaBook; Console.WriteLine("Пiсля видалення книжки:"); Console.WriteLine(bookshelf); Console.WriteLine(); } catch (Exception ex) { Console.WriteLine("------------Виняток:------------"); Console.WriteLine(ex.GetType()); Console.WriteLine("-------------Змсiт:-------------"); Console.WriteLine(ex.Message); Console.WriteLine("-------Трасування стеку:-------"); Console.WriteLine(ex.StackTrace); } } } }
Файл з XAML-кодом основного вікна залишається без змін:
<Window x:Class="WpfBookshelfApp.MainWindow" 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:WpfBookshelfApp" mc:Ignorable="d" Title="Книжкова полиця" Height="450" Width="685"> <DockPanel> <Grid Height="54" DockPanel.Dock="Top" VerticalAlignment="Top"> <Button Content="Відкрити" Height="42" HorizontalAlignment="Left" Margin="5,6,0,0" Name="ButtonOpen" VerticalAlignment="Top" Width="103" Click="ButtonOpen_Click" /> <Button Height="42" HorizontalAlignment="Left" Margin="115,6,0,0" Name="ButtonSortByTitle" VerticalAlignment="Top" Width="103" Click="ButtonSortByTitle_Click"> <Grid> <TextBlock Text="Сортувати за назвою" TextWrapping="Wrap" TextAlignment="Center" /> </Grid> </Button> <Button Height="42" HorizontalAlignment="Left" Margin="225,6,0,0" Name="ButtonSortByAuthorsCount" VerticalAlignment="Top" Width="103" Click="ButtonSortByAuthorsCount_Click"> <Grid> <TextBlock Text="Сортувати за кількістю авторів" TextWrapping="Wrap" TextAlignment="Center" /> </Grid> </Button> <TextBox Height="24" HorizontalAlignment="Left" Margin="335,14,0,0" Name="TextBoxSearch" VerticalAlignment="Top" Width="109" /> <Button Content="Знайти" Height="42" HorizontalAlignment="Left" Margin="450,6,0,0" Name="ButtonSearch" VerticalAlignment="Top" Width="103" Click="ButtonSearch_Click" /> <Button Content="Зберегти" Height="42" HorizontalAlignment="Left" Margin="560,6,0,0" Name="ButtonSave" VerticalAlignment="Top" Width="103" Click="ButtonSave_Click" /> </Grid> <DataGrid AutoGenerateColumns="False" Height="130" Name="DataGridAuthors" DockPanel.Dock="Bottom" VerticalAlignment="Bottom"> <DataGrid.Columns> <DataGridTextColumn Header="Ім'я" Width="100" x:Name="ColumnName" /> <DataGridTextColumn Header="Прізвище" Width="100" x:Name="ColumnSurname" /> </DataGrid.Columns> </DataGrid> <DataGrid AutoGenerateColumns="False" Name="DataGridBooks" SelectionChanged="DataGridBooks_SelectionChanged"> <DataGrid.Columns> <DataGridTextColumn Header="Назва" Width="350" x:Name="ColumnTitle" /> <DataGridTextColumn Header="Рік видання" x:Name="ColumnYear" /> </DataGrid.Columns> <DataGrid.ContextMenu> <ContextMenu> <MenuItem Header="Додати рядок" Name="MenuItemAdd" Click="MenuItemAdd_Click" /> <MenuItem Header="Видалити рядок" Name="MenuItemRemove" Click="MenuItemRemove_Click" /> </ContextMenu> </DataGrid.ContextMenu> </DataGrid> </DockPanel> </Window>
Аналогічно залишаємо без змін файл опису додаткового вікна:
<Window x:Class="WpfBookshelfApp.WindowSearchResults" 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:WpfBookshelfApp" mc:Ignorable="d" Title="Результати пошуку" Height="300" Width="600"> <Grid> <TextBox Name="TextBoxSearchResults" /> </Grid> </Window>
Код класів MainWindow
і Author
буде таким:
using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using BookshelfLib; namespace WpfBookshelfApp { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private BookshelfWithLINQ<Author> bookshelf = new(); public MainWindow() { InitializeComponent(); // Додаємо порожню книжку: bookshelf += new Book<Author>() { Title = "", Authors = new List<Author> { new Author() { Name = "", Surname = "" } } }; InitGrid(); } void InitGrid() { // Зв'язуємо таблицю DataGridBooks зі списком книг: DataGridBooks.ItemsSource = bookshelf.Books; DataGridBooks.CanUserAddRows = false; // Вказуємо, які колонки зв'язані з якими властивостями: ColumnTitle.Binding = new Binding("Title"); ColumnYear.Binding = new Binding("Year"); // Показуємо авторів для обраної книжки: ShowAuthors(DataGridBooks.Items.IndexOf(DataGridBooks.SelectedItem)); } private void ShowAuthors(int index) { // Якщо індекс хибний, встановлюємо індекс 0 if (index < 0 || index >= bookshelf.Books.Count) { index = 0; } // Зв'язуємо таблицю DataGridAuthors зі списком авторів: DataGridAuthors.ItemsSource = bookshelf.Books[index].Authors; DataGridAuthors.CanUserAddRows = false; // Вказуємо, які колонки зв'язані з якими властивостями: ColumnName.Binding = new Binding("Name"); ColumnSurname.Binding = new Binding("Surname"); } private void DataGridBooks_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Відображаємо авторів книжки, орбаної в DataGridBooks: ShowAuthors(DataGridBooks.Items.IndexOf(DataGridBooks.SelectedItem)); } private void MenuItemAdd_Click(object sender, RoutedEventArgs e) { // Підтверджуємо зміни даних у таблиці: DataGridBooks.CommitEdit(); // Додаємо порожню книжку: bookshelf += new Book<Author>() { Title = "", Authors = new List<Author> { new Author() { Name = "", Surname = "" } } }; InitGrid(); } private void MenuItemRemove_Click(object sender, RoutedEventArgs e) { // Визначаємо індекс активного рядку: int index = DataGridBooks.SelectedIndex; // Підтверджуємо зміни даних у таблиці: DataGridBooks.CommitEdit(); // Видаляємо активний рядок: bookshelf.Books.RemoveAt(index); // Якщо видалили всі рядки, додаємо новий порожній: if (bookshelf.Books.Count == 0) { bookshelf = new BookshelfWithLINQ<Author>(); bookshelf += new Book<Author>("", 0, new Author()); InitGrid(); } DataGridBooks.ItemsSource = null; InitGrid(); } private void ButtonOpen_Click(object sender, RoutedEventArgs e) { // Створюємо діалогове вікно та налагоджуємо його властивості: Microsoft.Win32.OpenFileDialog dlg = new(); dlg.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory; // поточна тека dlg.DefaultExt = ".xml"; dlg.Filter = "Файли XML (*.xml)|*.xml|Усі файли (*.*)|*.*"; if (dlg.ShowDialog() == true) { try { bookshelf.ReadBooks(dlg.FileName); } catch (Exception) { MessageBox.Show("Помилка читання з файлу"); } InitGrid(); } } private void ButtonSave_Click(object sender, RoutedEventArgs e) { // Створюємо діалогове вікно та налагоджуємо його властивості: Microsoft.Win32.SaveFileDialog dlg = new(); dlg.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory; dlg.DefaultExt = ".xml"; dlg.Filter = "Файли XML (*.xml)|*.xml|Усі файли (*.*)|*.*"; if (dlg.ShowDialog() == true) { try { bookshelf.WriteBooks(dlg.FileName); MessageBox.Show("Файл збережено"); } catch (Exception) { MessageBox.Show("Помилка запису в файл"); } } } private void ButtonSortByTitle_Click(object sender, RoutedEventArgs e) { bookshelf.SortByTitle(); InitGrid(); } private void ButtonSortByAuthorsCount_Click(object sender, RoutedEventArgs e) { bookshelf.SortByAuthorsCount(); InitGrid(); } private void ButtonSearch_Click(object sender, RoutedEventArgs e) { string sequence = TextBoxSearch.Text; if (sequence.Length == 0) { return; } // Знаходимо книжки за ознакою: var found = bookshelf.ContainsCharacters(sequence); // Формуємо рядок результатів: string text = ""; foreach (var book in found) { text += book + "\n"; } // Створюємо нове вікно: WindowSearchResults windowSearchResults = new(); windowSearchResults.TextBoxSearchResults.Text = text; windowSearchResults.ShowDialog(); } } // Клас для опису автора public class Author { [System.Xml.Serialization.XmlAttributeAttribute()] public string Surname { get; set; } = ""; [System.Xml.Serialization.XmlAttributeAttribute()] public string Name { get; set; } = ""; // Перевизначення еквівалентності public override bool Equals(object? obj) { if (obj == null) { return false; } Author author = (Author)obj; return author.Surname == Surname && author.Name == Name; } // Визначення представлення у вигляді рядку: public override string ToString() { return Name + " " + Surname; } // Визначається у парі з Equals() public override int GetHashCode() { return base.GetHashCode(); } } }
Застосовано додатковий контроль null-сумісних типів, нові можливості створення нових об'єктів new
()
та ініціалізації списків і властивостей. Видалені зайві using
-директиви.