0

I have following code snippet in xaml:

<UserControl x:Class="Ournamespace.OurClassName"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    ...
             d:DesignHeight="250" d:DesignWidth="774" Loaded="UserControl_Loaded">

....
<Button Grid.Column="0" x:Name="Button_NewMarker" Style="{StaticResource ViewpointFlatButtonStyle}" Width="90" Height="65" 
    VerticalAlignment="Top" Click="Button_NewMarker_Click" x:FieldModifier="public" Margin="0,0,0,0" Grid.Row="1">
    <BitmapImage UriSource="Icons/markers_add_disabled.png" />
</Button>

and I have tried to replace image on button dynamically, by loading new image

if( !imgCache.ContainsKey(path) )
{
    BitmapImage bi = new BitmapImage();
    bi.BeginInit();
    bi.UriSource = new Uri(path, UriKind.Relative);
    bi.DownloadFailed += bi_DownloadFailed;
    bi.DecodeFailed += bi_DecodeFailed;
    bi.EndInit();
    imgCache[path] = bi;

}
Button_NewMarker.BeginInit();
Button_NewMarker.Content = imgCache[path];
//Button_NewMarker.Content = oldbmp;
Button_NewMarker.EndInit();

There is no error occurring (overridden events for this) and BitmapImage seems to be replaced - but for some reason it's grey. Images are added to project as resources, and first image loaded seems to be working - but not dynamically replaced one.

I have tried also to use <Image ... > and even <Image ... <ImageBitmap - but all of them are not working - I suspect it has something to do with our control being UserControl.

What I have seen in internet - there is huge amount of recommendations of what and how should be done - I want now this to be done with absolute minimum amount of code - and preferably without using binding and templating. Binding can be proposed as second step after everything is done manually.

Clemens
  • 123,504
  • 12
  • 155
  • 268
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
  • Maybe you could try to bind it from ViewModel? – Sasha Jan 11 '17 at 11:26
  • Can you post whole answer as answer ? I would prefer to make change first without binding, just to understand the concept. Binding as advanced mechanism of replicating data can be done next if wanted. – TarmoPikaro Jan 11 '17 at 11:29
  • have a look here http://stackoverflow.com/questions/20586/image-urisource-and-data-binding/862583#862583 – Sasha Jan 11 '17 at 11:51

1 Answers1

1

If image files are managed as resource files (i.e. project files which have their Build Action set to Resource) you should load them by a Resource File Pack URI.

Assuming a project folder Images with an image file Test.png:

var bi = new BitmapImage(new Uri("pack://application:,,,/Images/Test.png"));

Using the file name as key, the abobe would probably look like:

var path = "Test.png";
var uri = "pack://application:,,,/Images/" + path;

imgCache[path] = new BitmapImage(new Uri(uri));
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • To my best understanding I'm using already similar technique - new Uri(path, UriKind.Relative); - only in your case you're using absolute url. Both approaches works fine, why to replace one method with another if result will be the same ? – TarmoPikaro Jan 11 '17 at 11:33
  • `new Uri(path, UriKind.Relative)` is something different, i.e. a relative URI to local file. Pack URI accesses a resource file that is compiled into the assembly. Regarding "both approaches works fine", then what is your question about? – Clemens Jan 11 '17 at 11:34
  • From debugger I can see following: imgCache[path] is displayed as `"*{Icons/markers_add_disabled.png}"` but after executing this line `Button_NewMarker.Content = imgCache[path];` in watch window this becomes: `{pack://application:,,,/VdcUi;component/Icons/markers_add_disabled.png}` So I'm not sure how path is resolved, but I suspect it's resolved correctly. Also bi_DownloadFailed& bi_DecodeFailed are not called. – TarmoPikaro Jan 11 '17 at 11:42
  • Does that mean the Button shows the new image as Content? – Clemens Jan 11 '17 at 11:43
  • Maybe - but button looks like grey still. What else could be wrong in this assignment scenario ? I have tried also to assign width / height, but it does not affect overall behavior. – TarmoPikaro Jan 11 '17 at 12:14
  • Hmm.... I have added extra 'bi.CacheOption = BitmapCacheOption.OnLoad;' and now I can see exception happening while trying to load that bitmap image. But it does not work now by either relative or absolute paths. Can you tell me how image should be embedded into .dll and how to determine it's full path ? – TarmoPikaro Jan 11 '17 at 12:30
  • It should be a file in your Visual Studio project with a `Build Action` set to `Resource`. – Clemens Jan 11 '17 at 12:33
  • Thanks, this helped me. I've upvoted and marked your answer. Also edited it and added more comments. – TarmoPikaro Jan 11 '17 at 13:27