Reputation: 10723
My code:
<Image Height="100" Width="100" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image.Source>
<BitmapImage DecodePixelWidth="100">
<BitmapImage.UriSource>
<PriorityBinding>
<Binding Path="MyModel1.ImagePath"/>
<Binding Path="MyModel2.ImagePath"/>
</PriorityBinding>
</BitmapImage.UriSource>
</BitmapImage>
</Image.Source>
</Image>
In my viewmodel, the value of ImagePath:
public object ImagePath
{
get { return new Uri("F:/myFolder/default.png", UriKind.Absolute); }
}
The path F:/myFolder/default.png exists. I get the error: Property 'UriSource' or property 'StreamSource' must be set. Why is this happening? Where am I making a mistake?
Upvotes: 1
Views: 3440
Reputation: 69985
Just use the plain string
file paths and let the Framework convert them to BitmapImage
elements:
public string ImagePath
{
get { return new "F:/myFolder/default.png"; }
}
...
<Image Height="100" Width="100" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image.Source>
<PriorityBinding>
<Binding Path="MyModel1.ImagePath"/>
<Binding Path="MyModel2.ImagePath"/>
</PriorityBinding>
</Image.Source>
</Image>
Upvotes: 0
Reputation: 25623
The problem is that you cannot initialize a BitmapImage
if you don't have a UriSource
or StreamSource
immediately available. You don't have a source immediately available because you are providing it via a Binding
, and bindings are not available until the data context has been set and the binding has been processed, which does not happen immediately.
You will need to defer creation of the BitmapImage
until the sources are available. You can do this with a custom converter:
public class ImageConverter : IValueConverter
{
public ImageConverter()
{
this.DecodeHeight = -1;
this.DecodeWidth = -1;
}
public int DecodeWidth { get; set; }
public int DecodeHeight { get; set; }
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
var uri = value as Uri;
if (uri != null)
{
var source = new BitmapImage();
source.BeginInit();
source.UriSource = uri;
if (this.DecodeWidth >= 0)
source.DecodePixelWidth = this.DecodeWidth;
if (this.DecodeHeight >= 0)
source.DecodePixelHeight = this.DecodeHeight;
source.EndInit();
return source;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
return Binding.DoNothing;
}
}
<Image Height="100"Width="100" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image.Source>
<PriorityBinding>
<Binding Path="Model1.ImagePath" Converter="{StaticResource ImageConverter}" />
<Binding Path="Model2.ImagePath" Converter="{StaticResource ImageConverter}" />
</PriorityBinding>
</Image.Source>
</Image>
...and drop this in your resources:
<l:ImageConverter x:Key="ImageConverter" DecodeWidth="100" />
Upvotes: 3