Reputation: 860
I am new to WPF and MVVM, and currently have the following problem, which I cannot wrap my head around.
I have a C# image database library with a database which looks roughly like this:
class Database
{
List<Image> Images;
}
class Image
{
string Path;
Bitmap Thumbnail;
List<MetaEntry> MetaData;
}
class MetaEntry
{
string Key;
string Value;
}
Now, I would like to display this database in a XAML list view. Where I can edit the meta data. Because I have other code dependent on the library API, I have to basically copy 90% of the data structures into view models, just so I can add my INotifyPropertyChanged
:
class ImageViewModel : INotifyPropertyChanged
{
// All members are hooked up to INotifyPropertyChanged
string Path;
Bitmap Thumbnail;
ObservableCollection<MetaEntryViewModel> MetaData;
}
class MetaEntryViewModel : INotifyPropertyChanged
{
// All members are hooked up to INotifyPropertyChanged
string Key;
string Value;
}
I can then use these view models, to write my database viewer view model and my XAML.
class Viewer : INotifyPropertyChanged
{
public ObservableCollection<ImageViewModel> Images; // Hooked up to Database.Images
public Image SelectedImage; // Notifies when changed
}
<StackPanel>
<Image Source="{Binding SelectedImage.Thumbnail, Converter={StaticResource ImageConverter}}" />
<ListBox ItemsSource="{Binding SelectedImage.MetaData}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Key}" />
<TextBox Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Images}"
SelectedItem="{Binding SelectedImage, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Thumbnail, Converter={StaticResource ImageConverter}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
(Here ImageConverter is a helper, which loads images from file to display them.)
So far, this works well as a meta data viewer. However, editing is not possible because I somehow have to propagate my changes back to the database. Implementing the back propagation is not exactly hard, but leads to the problem I am currently not able to understand or solve.
Writing code to hock up your model to your view, and then code to hook your view to the model seems very excessive. Furthermore it leads to lots of duplicate code with lots of edge cases which are hard to debug. Especially, when you are trying to hook up multiple view to the same model (e.g. a meta data filter). Is there an easier way to do all this?
Do I really need to blow up my GUI code, just to get some simple database editing going? Like:
Database database = LoadFromFile();
database.Images[5].MetaData[3].Value = "new value";
database.Images.RemoveAt(7);
SaveToFile();
Upvotes: 0
Views: 98
Reputation: 703
If you can't change the models (Image
and MetaEntry
), another approach, which would still require you to create view models, is to wrap your models in view models. Based on the code you showed, it seems that you are copying the properties from the model to the view model, but when the view model changes, the model does not. If I understand the problem correctly, then you could do something like this
class MetaEntryViewModel : INotifyPropertyChanged
{
// Assign this in the constructor
private readonly MetraEntry _metaEntry;
// All members are hooked up to INotifyPropertyChanged
public string Key
{
get => _metaEntry.Key;
set
{
_metaEntry.Key = value;
NotifyPropertyChanged(this, "Key");
}
}
// Other properties following the same pattern
}
While you still have to create these view models, when the view model changes, the backing model changes as well, and therefore those backing models can be persisted.
Upvotes: 1