Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List of text blocks in wpf

Tags:

c#

wpf

I'm have collections of books and ListVew for representation books data. I'm try to make list of text blocks. Each text block need to convert data with convertor which take one model and give one string with data, but i don't know how to bind collections and pass one model to convertor.

Book model:

namespace Books.Models
{
    public class Book : IModel
    {
        public Book()
        {
            Authors = new List<Author>();
            Tags = new List<string>();
        }
        public string Name { get; set; }
        public List<Author> Authors { get; set; }
        public string ISBN { get; set; }
        public int Pages { get; set; }
        public List<string> Tags { get; set; }
        public int PublicationYear { get; set; }
        public House House { get; set; }
    }
}

Books collection:

namespace Books.Collections
{
    public class ModelsCollection : Dictionary<string, IModel>
    {
        public void Add(IModel model)
        {
            Add(model.Name, model);
        }
        public IEnumerable<IModel> GetAll()
        {
            foreach (IModel model in Values)
                yield return model;   
        }
    }
}

Convertor:

namespace Books
{

    [ValueConversion(typeof(ModelsCollection), typeof(string))]
    public class BooksConvertor : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Book book = (Book)value;
            return book.Name + " - " + string.Join(", ", book.Authors.Select(x => x.Name));
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

ListView in XAML

    <ListView >
        <TextBlock Text="{Binding Path=Book,Converter={StaticResource BooksConvertor}}"/>
    </ListView>
like image 499
Rodion Avatar asked Sep 11 '25 13:09

Rodion


1 Answers

First, you'll need a way to set the DataContext of the Window/View you are working with. I've created a simple ViewModel to do so (using your Models).

public class ViewModel
{
    public List<IModel> Books { get; private set; }

    public ViewModel()
    {
        var modelCollection = new ModelsCollection();

        for (var i = 0; i < 10; i++)
        {
            var testBook = new Book
            {
                Name = "Test Book " + i
            };
            testBook.Authors.Add(new Author
            {
                Name = "Test Author " + i
            });

            modelCollection.Add(testBook);;
        }

        Books = modelCollection.GetAll();
    }
}

In the Ctor of the code-behind of the Window, simply do:

DataContext = new ViewModel();

Next, your ListView needs to bind to the collection of Books specified in your ViewModel, and also have a pre-defined template to bind to each Book object correctly. You'll need to update your ListView to:

<ListView ItemsSource="{Binding Books}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ., Converter={StaticResource BooksConvertor}}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Lastly, you'll need to update your converter to use an IModel type, since this is the data that is being passed in.

[ValueConversion(typeof(IModel), typeof(string))]
public class BooksConvertor : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var book = value as Book;
        if (book != null)
        {
            return book.Name + " - " + string.Join(", ", book.Authors.Select(x => x.Name));
        }
        else
        {
            return "";
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
like image 149
d.moncada Avatar answered Sep 13 '25 04:09

d.moncada