This question is an exact duplicate of:
- Image is saved and shows in Win File Explorer, doesn't load in app or VS
I have the option to add a new Customer in my application. The Customer is stored in the DB with its ID, Name, and Logo. Logo is just the string of the image file (like logo.png)
The adding of the logo seems fine. When I select an Image, it shows in the CustomerAddView.
After adding the Customer, the CustomerAddView window closes. The Customer is created in the DB, the Logo value in the DB is fine.
The list of Customers in the main window is refreshed (CustomerListView). The other Customer's Logo's are working fine. But the new Customer's Logos (added with the AddView window) throw this warning:
System.Windows.Data Warning: 6 : 'DynamicValueConverter' converter failed to convert value '../../Media/Images/Logos/testlogo.png' (type 'String'); fallback value will be used, if available. BindingExpression:Path=Logo; DataItem='Customer_5A59789E69DE0B010CE32D4E23A696EDB09551158A85050E8CA80E51475D369B' (HashCode=45868004); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') IOException:'System.IO.IOException: Kan bron media/images/logos/testlogo.png niet vinden.
bij MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access)
bij System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
bij System.IO.Packaging.PackWebResponse.CachedResponse.GetResponseStream()
bij System.IO.Packaging.PackWebResponse.GetResponseStream()
bij System.IO.Packaging.PackWebResponse.get_ContentType()
bij System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
bij System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
bij System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy)
bij System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
bij MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
bij MS.Internal.Data.TargetDefaultValueConverter.Convert(Object o, Type type, Object parameter, CultureInfo culture)
bij MS.Internal.Data.DynamicValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
bij System.Windows.Data.BindingExpression.ConvertHelper(IValueConverter converter, Object value, Type targetType, Object parameter, CultureInfo culture)'
System.Windows.Data Error: 11 : Fallback value 'Default' (type 'String') cannot be converted for use in 'Source' (type 'ImageSource'). BindingExpression:Path=Logo; DataItem='Customer_5A59789E69DE0B010CE32D4E23A696EDB09551158A85050E8CA80E51475D369B' (HashCode=45868004); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') NullReferenceException:'System.NullReferenceException: De objectverwijzing is niet op een exemplaar van een object ingesteld.
bij System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
bij System.Windows.Data.BindingExpressionBase.ConvertValue(Object value, DependencyProperty dp, Exception& e)'
I would like to know why my logo image is there in the File Explorer, in the specified folder, but isn't displayed in the list of Customers as it should.
And I want to know why the images do work when added via Visual Studio's Solution Explorer, but don't work when I add them (to the same folder) via the CustomerAddView(Model).
Here's the files for adding a new Customer: CustomerAddView:
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Name="TBCustomerTitle" FontWeight="Bold">Customer name:</TextBlock>
<TextBlock Grid.Column="1" FontWeight="Bold" Margin="5,0">*</TextBlock>
<TextBox Name="TBCustomerData" Grid.Column="2" Grid.ColumnSpan="2"
Text="{Binding NewCustomer.Name, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<TextBlock Grid.Row="1" FontWeight="Bold">Customer logo:</TextBlock>
<Image Grid.Row="1" Grid.Column="2" MaxHeight="100" MaxWidth="100"
Source="{Binding NewCustomerLogo, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Row="1" Grid.Column="3" Content="Choose logo"
Command="{Binding SelectLogoCommand}"/>
<TextBlock Margin="0,10" Grid.Row="2" Grid.ColumnSpan="4">Fields marked with * are required fields.</TextBlock>
<Button Grid.Row="3" Grid.ColumnSpan="4" Margin="0,50,0,0"
Command="{Binding AddConfirmCommand}">Add this customer</Button>
</Grid>
CustomerAddViewModel:
class CustomerAddViewModel : INotifyPropertyChanged
{
private RelayCommand addConfirmCommand;
private RelayCommand selectLogoCommand;
Image customerLogo;
string logoDirectory = "../../Media/Images/Logos/";
DBCustomer dbCustomer = new DBCustomer();
#region Add Customer
public ICommand AddConfirmCommand
{
get { return addConfirmCommand ?? (addConfirmCommand = new RelayCommand(() => AddConfirmCustomer())); }
}
private void AddConfirmCustomer()
{
if(newCustomer.Logo != null)
{
customerLogo.Save(logoDirectory + newCustomer.Logo);
}
else
{
newCustomer.Logo = "Default.png";
}
if (!dbCustomer.Create(newCustomer))
{
return;
}
App.Messenger.NotifyColleagues("AddCustomerDone");
}
#endregion
#region Add logo
public ICommand SelectLogoCommand
{
get { return selectLogoCommand ?? (selectLogoCommand = new RelayCommand(() => SelectLogo())); }
}
private void SelectLogo()
{
OpenFileDialog chooseFile = new OpenFileDialog();
chooseFile.Title = "Select a logo";
chooseFile.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
"JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
"Portable Network Graphic (*.png)|*.png";
if(chooseFile.ShowDialog() == DialogResult.OK)
{
Stream reader = File.OpenRead(chooseFile.FileName);
customerLogo = System.Drawing.Image.FromStream((Stream)reader);
MemoryStream finalStream = new MemoryStream();
customerLogo.Save(finalStream, ImageFormat.Png);
// translate to image source
PngBitmapDecoder decoder = new PngBitmapDecoder(finalStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
NewCustomerLogo = decoder.Frames[0];
newCustomer.Logo = newCustomer.Name + ".png";
}
}
private ImageSource newCustomerLogo;
public ImageSource NewCustomerLogo
{
get
{
return newCustomerLogo;
}
set
{
newCustomerLogo = value;
OnPropertyChanged(new PropertyChangedEventArgs("NewCustomerLogo"));
}
}
#endregion
private Customer newCustomer = new Customer();
public Customer NewCustomer
{
get { return newCustomer; }
set { newCustomer = value; OnPropertyChanged(new PropertyChangedEventArgs("NewCustomer")); }
}
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
#endregion
}
CustomerListView
<ListBox.ItemTemplate>
<!-- This DataTemplate is used for every Customer object in the ListBox.-->
<DataTemplate>
<Border BorderThickness="2" BorderBrush="Black"
Padding="10" Margin="10"
Name="CustomerBorder">
<Grid Name="ItemGrid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Logo picture -->
<Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" HorizontalAlignment="Center"
Source="{helpers:ConcatString FrontString=../../Media/Images/Logos/, BindTo={Binding Path=Logo, FallbackValue=Default}}"
Height="{Binding ActualHeight, ElementName=ItemGrid}"/>
<!-- Customer name Row-->
<TextBlock Grid.Row="0" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold"
Name="CustomerTitle">
Customer:
</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="2"
Name="CustomerDataType"
Text="{Binding Path=Name}">
</TextBlock>
<!-- Environment name Row-->
<TextBlock Grid.Row="1" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold" />
<TextBlock Grid.Row="2" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT:
This screenshot might shed some light on my confusion.
I added the testlogo.png via the CustomerAddView(Model), the other 3 were added right in VS Solution Explorer.
As you can see:
- The logo's are all in the same directory.
- Only the logo's added via VS Solution Explorer show in VS Solution Explorer. The new one doesn't.
- The new logo doesn't show in the CustomerListView. The others do.
EDIT 2:
Is it maybe a better idea to save the image to the database instead of saving the file name as a string in the database?