OK, here's my issue :
I've got a custom class, with a list of items - each of which has an image path associated with it
I've added a folder WITH the images inside the project (so I suppose there are being added in the XAP too, huh?)
When I'm trying to bind the Source of an image item in XAML, it's not working.
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<Image Height="100" Width="100" Margin="12,0,9,0" Source="/AlbumArt/{Binding AlbumArt}"/>
<StackPanel Width="311">
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}"/>
<TextBlock Text="{Binding Author}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What am I doing wrong? Any ideas?
P.S.
I've also tried Source="{Binding AlbumArt}" but it's still not displaying anything.
The craziest thing is that, if I set the Source to a specific image (e.g. /AlbumArt/someImage.jpg), the image seem to work fine in Visual Studio & the Emulator.
I don't think Binding works that way. If it is not possible to prepend the string "/AlbumArt/" to your image path property (which is AlbumArt), I would suggest using a converter to do so.
Also, formatting strings only works when the target property is a string so StringFormat is out. Someone correct me if I'm wrong about StringFormat
If you have binding issues always check the output window for details. That is where information about binding errors is displayed.
This Source="/AlbumArt/{Binding AlbumArt}" won't work because it will just be treated as a string.
Without seeing your class it's hard to be certain but the property you're binding to ("AlbumArt") should be a Uri and not a string and it should be populated with a relative Uri to the image. That image should also be set to having the build action of Content.
what you have to is this..
<Image Height="100" Width="100" Margin="12,0,9,0" Source="{Binding ImagePath}"/>
as you said you have list of items( i think it would be class that also having paths of images ) so make this property in this class and for every item put the path in this property for coresponding item.
private string _ImagePath;
public string ImagePath
{
get
{
return _ImagePath;
}
set
{
_imagePath = value;
}
}
it would be better if you implement INotifyPropertyChanged in your item class.
How about getting more nesty.
private string _AlbumArt;
public string AlbumArt
{
get
{
return _AlbumArt;
}
set
{
if(_AlbumArt!=null)
_AlbumArt=#"/AlbumArt/"+ value;
}
}
and Binding
<Image Height="100" Width="100" Margin="12,0,9,0" Source="{Binding AlbumArt}"/>
I'm pretty sure you've just used the wrong path, try this one....
"/ApplicationName;component/AlbumArt/{Binding AlbumArt}"
Replace the ApplicationName section with your applications name of course. MAKE SURE TO REPLACE SPACES IN IT WITH %20
Related
This question already has an answer here:
How do I change an image source dynamically from code-behind in WPF with an image in Properties.Resources?
(1 answer)
Closed 1 year ago.
XAML code:
<ListView x:Name="Toolbar" Grid.Row="1" ItemsSource="{Binding List}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel MouseLeftButtonDown="Lamp_Click" Name="Lamp" Background="White" Width="34" Height="35">
<Grid Height="30">
<Image Source="images/{Binding Path}">
</Image>
<TextBlock Text="{Binding Name}" FontSize="7" TextAlignment="Center" Margin="-1,19,1,-12"></TextBlock>
</Grid>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# code:
public class MyClass
{
public static List<ViewModel> List{ get; set; } = GetAll();
public static List<ViewModel> GetAll()
{
// get records from data base.
}
}
This code has syntax error. How can I change images/{Binding path} to a valid. why this code has error? I'm really confused. Please help me.
<Image Source="images/{Binding Path}">
XAML doesn't support this kind of half binding thing you're doing, you either bind something or you don't. And even if it did, it wouldn't work like that because Image.Source isn't a string, it's an ImageSource.
Instead you need to create a converter that converts your Path binding (a string) to an ImageSource by instantiating a BitmapImage and setting its source to load the image asynchronously.
I'm binding a List<string> to my ListBox in WPF using MVVM
At the moment I have
<ListBox ItemsSource="{Binding FileContents}"></ListBox>
File Contents in my ViewModel is simply
public List<string> FileContents {get;set;}
And the FileContents values are set in the constructor of the ViewModel, as such there is no need to worry about INotifyProperty
Everything works fine so far. I can see the list displayed in my ListBox as desired.
Now I need to provide a template! This is where it goes wrong
<ListBox ItemsSource="{Binding FileContents}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is where it all goes wrong! My understanding is that I only need to do <TextBox Text = "{Binding}" because the ListBox is already bound to the List<string> property (called FileContents)
However, when I run the above Visual Studio gives me
The application is in break mode
If I update the code to
<TextBox Text = "Some String Value"
then it works fine
I don't understand what I've done wrong.
Set the Mode of the Binding to OneWay:
<TextBox Text="{Binding Path=., Mode=OneWay}" />
The default binding mode for the Text property of a TextBox is TwoWay but this won't work when you bind to a string in a List<string>.
Binding to a string directly is only possible one way. This means you are only able to bind read only like
<TextBox Text="{Binding Mode=OneWay}"/>
or
<TextBox Text="{Binding .}"/>
The reason is simple: Changing the string means you are removing and adding an item to your list. This is simply not possible by changing the string in a TextBox.
A solution is to wrap the content in a class like
public class FileContent
{
public string Content { get; set; }
}
and bind to a list of List<FileContent> by using <TextBox Text="{Binding Content}"/> as template.
I've ran into a bit of a wall with being able to bind data of my custom object list to a ListBox in WPF.
This is the custom object:
public class FileItem
{
public string Name { get; set; }
public string Path { get; set; }
}
And this is the list:
private List<FileItem> folder = new List<FileItem>();
public List<FileItem> Folder { get { return folder; } }
The list gets populated and maintained by a FileSystemWatcher as files get moved around, deleted, renamed, etc. All the list does is keeps tracks of names and paths.
Here's what I have in the MainWindow code-behind file (it's hard coded for testing purposes for now):
FolderWatcher folder1 = new FolderWatcher();
folder1.Run(#"E:\MyApp\test", "*.txt");
listboxFolder1.ItemsSource = folder1.Folder;
Here's my XAML portion:
<ListBox x:Name="listboxFolder1" Grid.Row="1" BorderThickness="0"
ItemsSource="{Binding}"/>
Unfortunately, the only thing that gets displayed is MyApp.FileItem for every entry. How do I display the specific property such as name?
You will need to define the ItemTemplate for your ListBox
<ListBox x:Name="listboxFolder1" Grid.Row="1" BorderThickness="0"
ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The easiest way is to override ToString on your FileItem, (The listbox uses this to populate each entry)
public override string ToString()
{
return Name;
}
Each item in the list that ListBox shows automatically calls the ToString method to display it, and since you didn't override it, it displays the name of the type.
So, there are two things you can do here.
Override the ToString method like Sayse suggested.
Use DataTemplate and bind each of your properties seperatly
In your resource add the template with a key
<DataTemplate x:Key="fileItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Path}"/>
</StackPanel>
</DataTemplate>
and give it as your listbox ItemTemplate
<ListBox x:Name="listboxFolder1" Grid.Row="1" BorderThickness="0" ItemsSource="{Binding}" ItemTemplate="{StaticResource fileItemTemplate}">
In case anyone comes across this now via search, I just encountered pretty much the same issue in a C# UWP app.
While the XAML bits in Nitin's answer above were necessary, they didn't fix the issue alone -- I also had to change my equivalent of Folder to be an ObservableCollection, rather than a List, to get the ListBox to show the property I needed.
I have an app for windows 8 that needs to take a Json string and deseriaizes it into DATACONTRACTS and it will display the information I wish in a Listbox that will have a max height and will scroll if greater than the max height.
The problem that im having it not so much as not being able to do it but rather not knowing how to do it.
So far I can deserialize the Json and I can specify where I want each item to go into the UI but what im trying to do is basically a for each item in the array I want it to make a new Stackpanel formatted with Textblocks that will have the information from the Json. I don't know how to this unfortunately and I don't really know what im searching for to get tutorials on how to do it
This is the code I have that takes the items from the json with a helper class and puts them in the Text of the TextBlocks.
var _FilterSaleList = new FilterSalesList();
var _Sales = await _FilterSaleList.FindSalesbyFilters();
string _SaleName = _Sales.sales[0].name.ToString();
string _SaleDescription = _Sales.sales[0].description.ToString();
string _SaleName1 = _Sales.sales[1].name.ToString();
string _SaleDescription1 = _Sales.sales[1].description.ToString();
int _TotalResults = _Sales.sales.Length;
SaleTitle.Text = _SaleName;
SaleDescription.Text = _SaleDescription;
SaleTitle1.Text = _SaleName1;
SaleDescription1.Text = _SaleDescription1;
This is the XAML code for the Listbox with 2 Stack panels already in it.
<ListBox Grid.Row="1">
<StackPanel Margin="0,0,0,5">
<TextBlock x:Name="SaleTitle" Text="" HorizontalAlignment="Center" Margin="0,0,0,5"/>
<TextBlock x:Name="SaleDescription" Text="" HorizontalAlignment="Center" MaxHeight="40" Margin="0,0,0,5" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Margin="0,0,0,5">
<TextBlock x:Name="SaleTitle1" Text="" HorizontalAlignment="Center" Margin="0,0,0,5"/>
<TextBlock x:Name="SaleDescription1" Text="" HorizontalAlignment="Center" MaxHeight="40" Margin="0,0,0,5" TextWrapping="Wrap"/>
</StackPanel>
</ListBox>
Below is an image of how I would like it to look.
even though everything works this way like I said I would like it so that each item from the json will make a new stackpanel and display the information as in the image. I don't know what its called when this is done so even a simple hint as to where to look would be great!
http://puu.sh/2biMZ
In XAML there is a very nice feature called Binding, which allows you to simply bind an object or a list of objects to visual element. This way, you don't have to "build" the graphical user interface manually in C# code.
This is a very large topic, so you should probably have a look at what is MVVM, it will help you leverage the power of Binding : http://channel9.msdn.com/Series/Building-Apps-for-Both-Windows-8-and-Windows-Phone-8-Jump-Start/Building-Apps-for-Both-Windows-8-and-Windows-Phone-8-03-Model-View-ViewModel
But for now, what you could is :
1/ Define your ListBox as following, with a DataTemplate for the ItemTemplate property :
<ListBox Grid.Row="1" x:Name="SalesListbox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,5">
<TextBlock x:Name="SaleTitle" Text="{Binding name}" HorizontalAlignment="Center" Margin="0,0,0,5"/>
<TextBlock x:Name="SaleDescription" Text="{Binding description}" HorizontalAlignment="Center" MaxHeight="40" Margin="0,0,0,5" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The DataTemplate will tell how each item of the list should be rendered. You should also notice how we used Binding for the Text properties in each textblock. It's bound to name and description which are the name of the properties in your model.
And then you can populate your ListBox with your data :
var filterSaleList = new FilterSalesList();
var salesByFilters = await filterSaleList.FindSalesbyFilters();
SalesListbox.ItemsSource = salesByFilters.sales;
I'm quite new to C# and Windows Phone 7 for that sake, but none the less, I've thrown myself into trying to make a small app for myself. Here's my problem:
I'm trying to set up a DataTemplate that will position my Name and Drinks variables that I've declared in MainPage.xaml.cs. Here's my action when button1 is clicked:
private void button1_Click(object sender, RoutedEventArgs e)
{
string Name = participantName.Text;
int Drinks = 0;
listBox1.Items.Add(Name + Drinks);
}
And here is my DataTemplate from MainPage.xaml
<ListBox Height="Auto" HorizontalAlignment="Stretch" Margin="7,74,0,0" Name="listBox1" VerticalAlignment="Stretch" Width="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="132">
<TextBlock Text="{Binding Path=Name}" FontSize="35" />
<StackPanel Width="370">
<TextBlock Text="{Binding Path=Drinks}" FontSize="35" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is that my data is not shown. It works perfectly without the DataTemplate, but as soon as I use it, my text simply doesn't get through. Your help is very much appreciated.
The template itself is ok. The bindings on the template, though, are currently incorrect.
When you add a new item to the list box, you are just adding a plain old string (which is currently missing a space, BTW.) Your bindings, though, expect the object in the list to have a Name property and a Drinks property, which of course the string class does not have.
The usual solution here is to logically separate your data model from your presentation, by creating a class to store the data itself (probably PersonDrink, with the appropriate Name and Drinks properties) and then adding those objects to the list.
You should read up on the MVVM pattern, as it provides an excellent way to ensure that changes in your data are reflected in your view, and visa versa.
http://amarchandra.wordpress.com/2011/12/18/binding-multiple-object-in-wp7-using-listbox/
Here is a sample for binding data using a datatemplate. I hope this might help you.