Im trying to bind a list of images to a Listbox, but all I get is a list of Type names
<ListBox x:Name="PhotosListBox" ItemsSource="{Binding MyImages}" />
The MyImages is a List<BitMapImages>
Right now It just returns a list of System.Windows.Media.Imaging.BitmapImage instead of showing the Images
EDIT
For further ref, here is the final code.
<ListBox x:Name="PhotosListBox" ItemsSource="{Binding MyImages}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Stretch="Uniform"></Image>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
By default, the ToString() method of the bound data type will be invoked, which by default will return the fully qualified type name.
You should define a custom ItemTemplate for the ListBox.
You need to use an ItemTemplate other than the default so that the ListBox knows how to handle the data type being passed to it.
See: http://msdn.microsoft.com/en-us/library/ms742521.aspx
Related
How can I change the Text of a TextBlock when the selection in my ListView changes?
I don't want do this manually...
All Items of the ListView are LogEntry's (class)... Can I use Binding in the Text-Attribute of the TextBlock to get a specific property of the selected Item?
Yes, in fact there are multiple solutions, i give you the most "WPF" like answer, but imo also the least flexible.
First you need to set the IsSynchronizedWithCurrentItem="True" property
Now if you select an item, the bound CollectionView will set the item as the CurrentItem.
Now your TextBox/Block can bind to this specific item via a special binding syntax using a '/'.
For Example:
<TextBlock Text="{Binding LogEntries/}"/>
of course you can get a specific property from the current item via binding aswell
<TextBlock Text="{Binding LogEntries/WarningMessage}"/>
Hope that helps.
assuming you have a listview like this:
<ListView ItemSource="{Binding LogEntries}" Name="logs" IsSynchronizedWithCurrentItem="True">
</ListView>
<ContentControl Content="{Binding ElementName=logs, Path=SelectedItem}" ContentTemplate="{StaticResource logTemplate}"/>
Now you need to provide that logTemplate in the Resources.
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:LogEntry}">
<TextBlock Text="{Binding Path=LogText}"/> <-- This is a Property-Binding of your custom class
</DataTemplate>
</UserControl.Resources>
The last thing missing is to provide the namespace to your local class LogEntry. If you use an awesome tool like Resharper, it will insert the namespace for you. Otherwise, here a sample declaration:
<UserControl xmlns:local="clr-namespace:My.App.Namespace.LogEntry;assembly=My.App"
... (rest of namespace declarations)
I have a TreeView databound to a CollectionViewSource Groups collection. This is so that I can display the data using the power of the CollectionViewSource, and the data itself also has a hierarchical structure, which is why I need the TreeView. I have a second control which is bound to the SelectedItem of the TreeView.
The problem is that when the group header is selected, the program crashes with the following exception.
{"A TwoWay or OneWayToSource binding cannot work on the read-only property 'Name' of type 'MS.Internal.Data.CollectionViewGroupInternal'."}
The objects in my TreeView contain a Name property that is two way bound in another control. The binding engine seems to find the Name property for the Group and attempt to bind to that. How can I prevent this exception from occuring? I would like for the rest of my program to treat it as if nothing is selected when the group header is selected, or disallow selecting the group header all together. Below is a simplified version of the code.
<TreeView
x:Name="CustomersTree"
ItemsSource="{Binding CustomersViewSource.Groups}"
ItemTemplate="{StaticResource CustomerGroupsTemplate}">
<MyUserControl DataContext="{Binding ElementName=CustomersTree, Path=SelectedItem, Mode=OneWay}" />
<HierarchicalDataTemplate x:Key="CustomerGroupsTemplate" ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource CustomerTreeItemTemplate}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CustomerTreeItemTemplate" ItemsSource="{Binding Customers}">
<StackPanel>
<Image Source="{Binding ImageSource}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</HierarchicalDataTemplate>
To be clear, the error is a result of the binding in the CustomerGroupsTemplate as far as I can tell, and changing this binding to OneWay results in the same error. The information in the tree shows up the way it is expected to, it is only when a group header is selected that the exception occurs.
The problem was the result of a two way binding within the user control. I ended up using a converter to check for the type of the object being bound, ignoring it if it wasn't the object I wanted.
I have a ListView displaying a list of items containing mainly two properties.
Each of these properties should ideally be chosen from two comboboxes.
Moreover, the choices available in the second combobox is depends on the first.
So here is the idea of the code I used:
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<ComboBox Name="combo1"
ItemsSource="{DynamicResource combo1Source}"
SelectedItem="{Binding FirstProperty}"
SelectionChanged="combo_SelectionChanged">
<ComboBox Name="combo2"
ItemsSource="{DynamicResource combo2Source}"
SelectedItem="{Binding SecondProperty}">
</StackPanel>
<DataTemplate>
<ListView.ItemTemplate>
</ListView>
The thing is, I don't know how to get the reference to combo2 from within combo_SelectionChanged (in C#).
Could you show me how to proceed?
The easiest thing you can do is add a Tag to combo1:
<ComboBox Name="combo1" Tag="{x:Reference combo2}" ... />
Which you then can just get from the sender in the event handler, e.g.
var combo2 = (sender as FrameworkElement).Tag as ComboBox;
Alternatively you could get the StackPanel from the Parent property and just take (ComboBox)Children[1]. I would not do this though as is breaks if the structure of your template changes.
You should not have a reference to combo2, but you should update the Collection combo2Source which is bound as ItemsSource for combo2...
So in the combo_SelectionChanged you just load the possible values for the actual selection of combo1 to the combo2Source Collection.
EDIT: To prevent thats its for all items the same:
Add a ValueConverter which choses for a selectedItem the corresponding collection of possible values:
<ComboBox ItemsSource="{Binding ElementName=Combo1, Path=SelectedItem, Converter={StaticResource SubSelectionConverter}}" />
Example of ValueConverter:
private Dictionary<Object, List<Object>> _PossibleValues;
public object Convert(Object data, ....)
{
if(PossibleValues.ContainsKey(data))
{
//return the possible values for the actual selected parent item
return(PossibleValues(data));
}
return null;
}
Can have look here on my question and different responses and the solution I found for my specific project:
Find an element in Data Template
Hope this helps.
Regards.
I'm using silverlight framework 4: I'm trying to list my items in a generic list to a listbox control: But the only data a receive is the classname itself.
lsBox => the listbox control
lsTags => generic type
My question is: how can I add my items in the generic list, to the listbox control?
my code is:
lsBox.ItemsSource = lsTags;
You can use DisplayMemberPath and SelectedValuePath properties of your ListBox control to tell ListBox which property's value should be displayed for every item and which property should be used for determening ListBox.SelectedValue property. Or use ListBox.ItemTemplate to display a complex data like this:
<ListBox x:Name="usersInGroupLBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsActive, Mode=TwoWay}" />
<TextBlock Text="{Binding User.UserName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Do not forget, you can use only public properties for binding. Check you class Tag.
The default behavior of ListBox (and most other controls) for displaying user types is to call the ToString() method. The default behavior of that is to display the class name.
What you should do depends on what you want to display, but if it's something simple like displaying the value of the Name property, just set the DisplayMemberPath property:
<ListBox Name="lsBox" DisplayMemberPath="Name" />
I have a data layer which is returning lists of classes containing data. I want to display this data in my form in WPF. The data is just properties on the class such as Class.ID, Class.Name, Class.Description (for the sake of example)
How can i create a custom control or template an existing control so that it can be given one of these classes and display its data in a data-bound fashion.
Thanks :)
You could use a ListBox and set its ItemsSource property to the list containing your data items. Then you define a DataTemplate for your type like this:
<DataTemplate x:Key="MyDataTemplate" DataType="{x:Type MyType}">
<StackPanel>
<TextBlock Text="{Binding ID}"/>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
...and tell the ListBox to use this DataTemplate by setting the ItemTemplate property.
It is also sufficient to just define the DataTemplate as above and give it no key. Then it will be used for all items which have the respective type.
BTW: You can find a more detailed example in MSDN on the page for the ItemTemplate property.