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>
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With