|
I have an issue with data binding to an Image Source. I have a browse button that the user clicks to select an image file. There is also a text field that the user can type the file name into (or the browse click event will fill in the field through data binding also). The issue I have is that as soon as the app starts I get this error: "ImageSourceConverter cannot convert from System.String." Of course the default imagePath="" since nothing has been selected yet. Unfortunately it appears the Image Source isn't smart enough to know that a null string or an empty string should just be ignored and no image should be loaded. What is the proper way to handle this situation? My second question is, why does this work? <Grid> <Image Source="{Binding ElementName=FileNameTextBox, Path=Text}" Margin="0,83,0,0" Stretch="Fill"/> <Button Height="33" HorizontalAlignment="Right" Margin="0,23,8,0" Name="button1" VerticalAlignment="Top" Width="68" Click="button1_Click">Browse</Button> <TextBox Height="34" Margin="12,23,83,0" Name="FileNameTextBox" VerticalAlignment="Top" /> </Grid> This is binding the image source property directly to the text control which is set by the browse button click code. Shouldn't this have the same problem? The initial value for the text box is an empty string (or null - it is not set in code). Shouldn't the image source binding be updated immediately when the app loads? Thank you. | | t ssw | Hello, Are you sure that the problem is in the binding? I copied and pasted your exmple code in a new window and works fine... <Grid> <Image Source="{Binding ElementName=FileNameTextBox, Path=Text}" Margin="0,83,0,0" Stretch="Fill"/> <Button Height="33" HorizontalAlignment="Right" Margin="0,23,8,0" Name="button1" VerticalAlignment="Top" Width="68" Click="button1_Click">Browse</Button> <TextBox Height="34" Margin="12,23,83,0" Name="FileNameTextBox" VerticalAlignment="Top" /> </Grid> Try to copy and paste that code in a new window/project . good luck. | | HomeroThompson | I believe the reason that the second example does not fire the error is that the Text is empty and not null. In your example, the value is null prior to you selecting something. If you can post the problem code here then we can try to help you resolve the issue. | | DeviantSeev | If you re-read the above, I said it worked. I don't understand why since the Image Source is bound to a text edit field that is empty. | | t ssw | Agreed, the text is empty, however, in my first example, the imagePath is also just an empty string and that shows the error I mentioned. Here is the xaml and code behind for my first question in my original post.
<Window x:Class="Practice5WPF_JS.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Practice5WPF_JS" Title="Window1" Height="421" Width="488" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Image Source="{Binding ImageName}" Margin="0,83,0,0" Stretch="Fill"/>
<Button Height="33" HorizontalAlignment="Right" Margin="0,23,8,0" Name="button1" VerticalAlignment="Top" Width="68" Click="button1_Click">Browse</Button>
<TextBox Height="34" Margin="12,23,83,0" Text="{Binding ImageName}" VerticalAlignment="Top" />
</Grid>
</Window>
And the code behind:
public partial class Window1 : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Set filter for file extension and default file extension
dlg.DefaultExt = ".jpg";
dlg.Filter = "Images (.jpg)|*.jpg";
if (dlg.ShowDialog() == true)
ImageName = dlg.FileName;
}
public string ImageName
{
set
{
if (value != imageName)
{
imageName = value;
OnPropertyChanged(MethodBase.GetCurrentMethod().Name.Remove(0, 4));
}
}
get
{
return imageName;
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
string imageName = "";
}
| | t ssw | Hey,
I changed the
OnPropertyChanged(MethodBase.GetCurrentMethod().Name.Remove(0, 4));
To read: OnPropertyChanged("ImageName"); and the application works as expected with no errors. :)
P.S. I also removed the xmlns:local reference in the xaml but I don't think it makes a difference. - Proposed As Answer byDeviantSeev Thursday, September 17, 2009 5:10 PM
-
| | DeviantSeev | It doesn't for me. Sorry. There is no difference between those two - one gets it from the property name, the other is hard coded. Also, see the great Karl for how this works. http://karlshifflett.wordpress.com/2009/08/02/inotifypropertychanged-how-to-remove-the-property-name-string-code-smell/ | | t ssw | Hi t ssw, I can reproduce the problems. However, based on my test, the following code produces the same exception as well:
<Grid>
<Image Source="{Binding ElementName=FileNameTextBox, Path=Text}" Margin="0,83,0,0" Stretch="Fill"/>
<Button Height="33" HorizontalAlignment="Right" Margin="0,23,8,0" Name="button1" VerticalAlignment="Top" Width="68" Click="button1_Click">Browse</Button>
<TextBox Height="34" Margin="12,23,83,0" Name="FileNameTextBox" VerticalAlignment="Top" />
</Grid>
>Unfortunately it appears the Image Source isn't smart enough to know that a null string or an empty string should just be ignored and no image should be loaded. What is the proper way to handle this situation? It is not the Image source can not know the source type is null or empty string, but the exception to be thrown is on purpose. It's not hard to find that factor if you take a look at the source code of the ImageSourceConverter with reflector. The source code of ConvertFrom method of type ImageSourceConverter:
[SecurityCritical, SecurityTreatAsSafe]
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null)
{
throw base.GetConvertFromException(value);
}
if (((value is string) && !string.IsNullOrEmpty((string) value)) || (value is Uri))
{
UriHolder uriFromUriContext = TypeConverterHelper.GetUriFromUriContext(context, value);
return BitmapFrame.CreateFromUriOrStream(uriFromUriContext.BaseUri, uriFromUriContext.OriginalUri, null, BitmapCreateOptions.None, BitmapCacheOption.Default, null);
}
if (value is byte[])
{
byte[] rawData = (byte[]) value;
if (rawData != null)
{
Stream bitmapStream = null;
bitmapStream = this.GetBitmapStream(rawData);
if (bitmapStream == null)
{
bitmapStream = new MemoryStream(rawData);
}
return BitmapFrame.Create(bitmapStream, BitmapCreateOptions.None, BitmapCacheOption.Default);
}
}
else if (value is Stream)
{
Stream stream2 = (Stream) value;
return BitmapFrame.Create(stream2, BitmapCreateOptions.None, BitmapCacheOption.Default);
}
return base.ConvertFrom(context, culture, value);
}
You can ignore this exception in your application since it does not block the application. If you still don't want this to happen, you can try to create a custom type converter and reuse most of the code in current ImageSourceConverter to converter string to image. If you have any problem, please feel free to let me know. Best regards, Bruce Zhou
Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework! If you have any feedback, please tell us. | | Bruce.Zhou | Thank you for the reply. It is strange that the element to element binding doesn't work on your machine buts works on my machine. This was what confused me since I had looked at the ImageConverter code when the exception was thrown from it. Where would I catch this exception (and this exception only)? I don't want a catch all at some high level. | | t ssw | Both methods works on my machine, and I can see the exception thrown from the output window. However, it does not block the application. As I mentioned above, if you don't want to see the exception, you may need to create a customized TypeConverter. Best regards, Bruce Zhou
Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework! If you have any feedback, please tell us. | | Bruce.Zhou | Hi t ssw, How's the problem going now? Did you succeed in creating new converter? If any help is needed, please feel free to let me know. Best regards, Bruce Zhou
Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework! If you have any feedback, please tell us. | | Bruce.Zhou |
|