I have a C# project where I have some PNG files in a Images directory.
The structure of the project can be simplified to:
|
ViewModel.cs
View.xaml
|
[Images]
\
MapImageLayer16.png
In my view I bind to an object containing a string property ImagePath, pointing to ../Images/MapImageLayer16.png, and another string property Name:
<ListBox x:Name="DataLayerList" ItemsSource="{Binding LayersFiltered, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=ImagePath}" Height="16"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now, the name comes trough fine. However, the image fails with the following description:
Failed to convert value '/Images/MapImageLayer16.png' (type 'String') to the target type using converter 'TargetDefaultValueConverter'. The fallback value will be used if it's available. IOException:'System.IO.IOException: Cannot locate resource 'images/mapimagelayer16.png'.
I tried all sorts of things by now:
changed the string value to ../Images/MapImageLayer16.png
changed the string value to pack://application:,,,/Images/MapImageLayer16.png
switched from string to Uri
Nothing works! How can I get the PNGs to show?
This is a common error when we forget to set the properties of the image as a Resource (on VisualStudio, Rightclic on the image > Properties > Build Action : Resource & Copy to OutputDirectory : Do not copy)
You also need to bind a BitmapImage, and not a string, to the Xaml Image control. In your CS code, the ImagePath must become :
public BitmapImage Source => new BitmapImage(new Uri(ImagePath, UriKind.Relative));
with ImagePath = "/Images/MapImageLayer16.png"
This looks like a typical WPF resource error to me. Open the {projectname}.csproj file and add this (adjust if necessary if the structure is not correct)
<ItemGroup>
<Resource Include="Images\MapImageLayer16.png" />
</ItemGroup>
Not in "PropertyGroup" but in "Project" as it can be seen here
Related
I have a problem - I want to bind into a GridView a class property which is a ObservableCollection.
the class code:
public class Moment
{
...
public ObservableCollection<Uri> PhotoFilePath { get; set; }
}
XAML
<GridView Grid.Row="0"
Name="PhotosGridView"
ItemsSource="{x:Bind moment}">
moment is a instance of Moment in MainPage.xaml
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Moment">
<Image Width="75" Height="75">
<Image.Source>
<BitmapImage UriSource="{x:Bind PhotoFilePath}" />
here i get
Severity Code Description Project File Line Suppression State
Error Invalid binding path 'PhotoFilePath' : Cannot bind type 'System.Collections.ObjectModel.ObservableCollection(System.Uri)' to 'System.Uri' without a converter
</Image.Source>
</Image>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Thanks in advance
The way you have it right now doesn't seem to make sense. moment is an instance of Moment, not a list of things (which is what ItemsSource expects). The list of things is the PhotoFilePath property on Moment (which, as an aside, is poorly named since it is a collection, not a single path).
I'm assuming what you really want to do is bind ItemsSource to moment.PhotoFilePath:
ItemsSource="{x:Bind moment.PhotoFilePath}">
You'll need to change your DataTemplate to just target a Uri:
<DataTemplate x:DataType="Uri">
Note that I am not positive if you can just say "Uri" there. I don't have a UWP project in front of me.
and then UriSource to each item inside of that property:
<BitmapImage UriSource="{x:Bind}" />
The UriSource property of BitmapImage expects type 'System.Uri'
but you are trying to bind it to 'ObservableCollection of System.Uri'
(PhotoFilePath property of your Moment class is an ObservableCollection of System.Uri)
The answer is in the error message
'Cannot bind type 'System.Collections.ObjectModel.ObservableCollection(System.Uri)' to 'System.Uri'
On windows phone 8 I have made a list box bandied with a web server data which are an image and a text sometimes the server returns only text as their are no image uploaded by the user. I need to display a placeholder image.
<ListBox Grid.Row="1" ItemsSource="{Binding places}" Name="mrx" Margin="0,10,0,0" Loaded="mrx_Loaded">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal" Margin="10,0,10,8">
<StackPanel Margin="10,0,10,8">
<TextBlock Text="{Binding name}" Foreground="Black" FontWeight="Bold" FontSize="40"/>
<Image Source="{Binding url}" Width="100" Height="100"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here how I access url:
public BitmapImage h { get; set; }
public BitmapImage url
{
get { return h; }
set
{
if (h == null)
{
h.UriSource = new Uri("profile-placeholder.gif", UriKind.RelativeOrAbsolute);
}
}
}
If your h == null when there is no image returned then there is easier way to do what you want - use TargetNullValue in Binding:
<Image Source="{Binding url, TargetNullValue='/Example;component/Resources/placeholder.png'}" Width="100" Height="100"/>
In above case be sure to set BuildAction of placeholder.png as Resource. (Example here is your project name, Resources is a path to the file). You can also bind directly to your h in this case.
If you insist on using designed property then:
I'm not sure how the rest of your code looks like, but but when you have defined binding like this:
<Image Source="{Binding url}" Width="100" Height="100"/>
When the item is being loaded the Getter of url is fired. So using Setter to repleace null with Bitmapimage won't help here (of course if you are not running Setter somewhere else, but defining Setter without value - kind a weird, implement it different or provide separate method.
Check if that would help:
public BitmapImage url
{
get
{
if (h == null)
return new BitmapImage() { UriSource = new Uri("/Projectname;component/path/profile-placeholder.gif", UriKind.Relative) };
return h;
}
}
Setting UriSource depends also how your file is defined in your project (Build Action), you can take a look here.
according to me you can try 2 options
1) make a image failed event of the image and when its called then set the default image as source.
2) put the image view inside a grid with background as the default image so if url comes then it will overlap the default image and show you user image and if it fails then the background of the image will be there as default image.
I hope this might help ......
Add a default image in your assets. Set this image path string as a default value to the "url" that you use for binding. and when you get a web response and parse it, check if there is a valid url path string for an image. If there is a valid url string parsed for the image, then assign it to "url" field else If there is no valid url string for the image, do not set it to the url field. The"url" string field will any way contain the default image that you set.
Hope this helps you. Thanks.
See Conditional text formatting XAML WP8
You should bind to url and set conditional trigger if url is null
<Image Source = "{Binding url} " Width="100" Height="100"/>
Here, instead of binding image source to URL directly, bind it to property having URL as a global variable and initiate URL to placeholder URL.
Example:
private string yourURL= "/Resources/Images/placeholder.png";
public string YourURL
{
get
{
return yourURL;
}
set
{
if (value != yourURL)
{
yourURL= value;
}
}
}
and statement will be like:
<Image Source="{Binding YourURL}" Width="100" Height="100"/>
I've set the XamDataTree image, but I don't want to copy the image folder to my debug folder every time. Instead I want to add the image to my project resources and use it from there. Currently no image is shown because it expects a path to an image where I give it an actual bitmap. The Icon property in the TreeNode is set in another part of the code.
This is my Xaml code:
<ig:XamDataTree
Grid.Row="1"
Name="MyTree"
ScrollViewer.CanContentScroll="True"
ItemsSource="{Binding ComparedContents}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
>
<ig:XamDataTree.CheckBoxSettings>
<ig:CheckBoxSettings CheckBoxVisibility="Visible" />
</ig:XamDataTree.CheckBoxSettings>
<ig:XamDataTree.CollapsedIconTemplate>
<DataTemplate>
<Image Source="{Binding Path=Icon}"/>
</DataTemplate>
</ig:XamDataTree.CollapsedIconTemplate>
<ig:XamDataTree.ExpandedIconTemplate>
<DataTemplate>
<Image Source="{Binding Path=Icon}"/>
</DataTemplate>
</ig:XamDataTree.ExpandedIconTemplate>
<ig:XamDataTree.GlobalNodeLayouts>
<ig:NodeLayout
Key="Children"
DisplayMemberPath="Text"
TargetTypeName="Model.TreeNode"
>
</ig:NodeLayout>
</ig:XamDataTree.GlobalNodeLayouts>
</ig:XamDataTree>
This is my model, each Property has a private store for the value and fires an event if it changes.
public class TreeNode : INotifyPropertyChanged
{
public Label Text;
public System.Drawing.Image Icon;
public ObservableCollection<TreeNode> Children;
}
Assuming you embedded the image into your application, you can use a pack uri to load the image into the node template. Instead of using an Image type on your Icon property you should use Uri and set it equal to something like this:
Icon = new Uri("pack://application:,,,/Resources/Images/icon.png");
You need to modify the binding in your templates a bit because the DataContext of this template is going to be a XamDataTreeNodeDataContext. This object has a Data property which will be your TreeNode object. Your binding should be updated to:
<Image Source="{Binding Path=Data.Icon}"/>
I have a little question.
I have a data template like that :
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="DangersItemTemplate">
<Grid Height="102" Width="447" Tap="Grid_Tap">
<Image Name="image" Source="{Binding Image}" HorizontalAlignment="Left" Width="90" />
<TextBlock Name="text" Text="{Binding Nom}" TextWrapping="Wrap" Margin="102,16,16,22"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I want to use the Textlock control in the CSharp code to pass the Text property to the second xaml page, but I can't find the name of the control, it's inaccessible.
Any idea ?
Your binding the Text of the TextBlock so you must have the value in your datacontext. I'd add this value to the Querystirng and navigate to the page.
var text = ((Whatever) DataContext).Nom;
string page2Uri = string.Foramt("/PAge2.xaml?Nom={0}", text);
NavigationService.Navigate(new Uri(page2Uri, UriKind.Relative));
And then to get the data out of the querystring you can use the OnNavigatedTo method in your page, and then inspect this.NavigationContext.QueryString["nom"]
Or have a look into something like the MVVM pattern.
I just use VB.Net but I am sure you can convert.
Just use any shared variable in the application.
Here you can see it in an SourceCode example:
http://www.activevb.de/rubriken/kolumne/kol_30/res/nachtscanner.zip
Just use Public Shared MyText As String
in Application Class. This vairable you can access anywhere.
You can also use INotifyPropertyChanged for that shared property to bind.
Alternatively you can use Navigation Query. Read more here:
How can I pass query string variables with NavigationService.Navigate?
I need to databind into a element inside my custom class. i've given the ItemSource as the ObservableCollection of telerik:RadTransitionControl via an attached property. However, I need to provide the image member as the source to Image control. I tried the following method and was unsuccessful.
<Grid Background="Black">
<telerik:RadTransitionControl x:Name="radControl" adRotator:AdRotatorExtensions.ItemChangeDelay="0:0:3"
adRotator:AdRotatorExtensions.CurrentSelectedIndex="0"
adRotator:AdRotatorExtensions.IndexChanged="{Binding TopItemCommand, Mode=OneWay}"
adRotator:AdRotatorExtensions.ItemsSource="{Binding Path=ImagePaths}"
VerticalAlignment="Center"
HorizontalAlignment="Center" Width="650">
<telerik:RadTransitionControl.Transition>
<telerik:MotionBlurredZoomTransition />
</telerik:RadTransitionControl.Transition>
<telerik:RadTransitionControl.ContentTemplate>
<DataTemplate>
<Image Source="{Binding Path=ImagePaths.AdImage}" />
</DataTemplate>
</telerik:RadTransitionControl.ContentTemplate>
</telerik:RadTransitionControl>
</Grid>
an ImagePaths object is already set as the DataContext for the item. this means that the binding is already pointing (so to speak) at an instance of the object. so, when you tell it to bind on ImagePaths.AdImage it does not know how to find the property you are looking for. Good news is, all you have to do is provide the path on the object-- remove the ImagePaths part (and the dot) and you should be good to go.
for example...
class something
{
public string someImage {...}
}
<DataTemplate> <!--------- the data context of this item is an instance of
my "something" class, so i need to set the path
to be the property on the object --->
<Image Source="{Binding Path=someImage}" />
</DataTemplate>
here is a very helpful article on debugging bindings in WPF
for more info here is an excellent article on MSDN
here is a datatemplate article from Dr. WPF