I am trying to copy a WinForms application using WPF.
In my application I have a ComboBox that is filled with the titles of movies, to let me search the movies. Now that I'm porting it to WPF, I want to use the ComboBox to display the title and poster image of the movie.
I have already created the ComboBox and the two objects, but don't know how to populate the ComboBox at runtime, because the Add method doesn't let me add the two objects at one.
combobox.items.add()
Please help me find out how to fill the ComboBox with text and images at runtime.
update: this is the xaml code for the combobox
<ComboBox x:Name="busca_pelicula" HorizontalAlignment="Left" VerticalAlignment="Top" Width="334" Margin="147,93,0,0" IsEditable="True">
<ComboBox.Effect>
<DropShadowEffect/>
</ComboBox.Effect>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Center" Name="PeliText"/>
<Image HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="50"/>
</ComboBox>
and the code for fill the combobox with my data from my movie database is this
busca_pelicula.Items.clear();
using sql stuff to retrieve title and movie poster
BitmapImage ImagenPoster = new BitmapImage();
ImagenPoster.BeginInit();
ImagenPoster.UriSource = new Uri(wMediaPath+"Peli\\"+wNombrePoster);
ImagenPoster.EndInit();
busca_pelicula.Items.Add(? don't know what to put here)
Firstly you have to create a class similar to this:
public class Movie : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
public ImageSource Picture { get; set; }
}
Then in your xaml you have to change the combo as follow:
<ComboBox >
<ComboBox.ItemTemplate>
<ItemContainerTemplate>
<StackPanel>
<Image Source="{Binding Picture}"></Image>
<TextBlock ><Run Text="{Binding Name}"/></TextBlock>
</StackPanel>
</ItemContainerTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
this is the way to declare the wpf combobox with uge amount of data to let you "virtualize" the render
<ComboBox x:Name="busca_pelicula" HorizontalAlignment="Left" VerticalAlignment="Top" Width="334" Margin="147,93,0,0" IsEditable="True" Height="55" SelectionChanged="busca_pelicula_SelectionChanged" >
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.Effect>
<DropShadowEffect/>
</ComboBox.Effect>
<ComboBox.ItemTemplate>
<ItemContainerTemplate>
<StackPanel>
<TextBlock ><Run Text="{Binding Name}" /></TextBlock>
<Image Source="{Binding Picture}" Width="50" Height="50" HorizontalAlignment="Right"></Image>
</StackPanel>
</ItemContainerTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
now is working like a charm, the combobox only renders the 10 items that it is showing, hope that helps some one.
Related
I am developing A UWP app and I have a dropdown with the list of country names, flag and country Codes. When I click on the drop down the list of countries opens. But, if I click and press any letter(e.g I) it does not scroll to the list automatically where the list starts with I.
I have tried adding IsTextSearchEnabled property to the drop down but I am not getting the desired result. Please can anyone guide me what needs to be done here?
<ComboBox x:Name="CmbCountrylist" Height="auto" IsEditable="True"
IsTextSearchEnabled="True" Width="250" Margin="0,0,1,0" Background="red"
PlaceholderText="Select Country"
SelectionChanged="CmbCountryCodes1_SelectionChanged"
HorizontalAlignment="Left" VerticalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" ToolTipService.ToolTip="{Binding name}" >
<Image x:Name="ImgFlag" Width="16" Height="16" Margin="0,2,5,2" VerticalAlignment="Center" HorizontalAlignment="Left" Source="{Binding ImagePath}" />
<TextBlock x:Name="txtCountryName" Text="{Binding name}" />
<TextBlock x:Name="txtCode" Text="{Binding dial_code}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
From your description, the data source which binding is a class. In this case, please override the class's ToString() method to return the country name.
public class Country
{
// other properties
public override string ToString()
{
return name;
}
}
When you enter text in a ComboBox, the ComboBox will match the data in the data list, but the ComboBox will not actively look for a property of the class, but instead look up the value of the ToString() method.
Best regards.
So here is my problem:
I want to access the items (and their properties), which are bound to a ListBox via a Bindable Collection, in a method of another class. (ShellViewModel)
More precise: I want to know which Items in this List are currently selected.
I'm using C#,Caliburn.Micro and the design pattern should be MVVM.
If the Button "Evaluate" is pressed, according to the selected ListBoxItems, different Methods get called.
So the XAML-Code in the ShellView is working fine, and also the "functional" code "works", but it is just working if I code directly in the xaml.cs-file. (big no,no)
Because I'm quite new to this topics, I've tried to create a new instance of the View for the access, but this will just give me control over the ListBox without "knowing" which Items are selected in the original instance.
Here is the general ListBox
<ListBox x:Name="MainListBox" ItemsSource="{Binding SCollection}"
Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="6" Grid.RowSpan="1"
SelectionMode="Multiple"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
MaxHeight="300" MinHeight="200" MaxWidth="340" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Padding="3,5,5,5" />
<TextBlock Text="{Binding Path=Info}" FontWeight="SemiBold" Padding="3,5,5,5" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="Evaluate" Background="Blue" Grid.Column="1" Grid.Row="7" MinWidth="80" Margin="5" Content="Test" Grid.ColumnSpan="1" />
So here are some questions:
Is there a similar solution like the binding of "SelectedItem" via xaml, which is bound to accessible variable, for multiple selected Items?(maybe I just missed something there?)
Is there a way to access the "original" instance of the ListBox(and therefore "live"-selected Items)?
To be clear:
Only problem, besides maybe other better solutions out there, is that, I want the called Method "Evaluate", which is bound to the button, have access to the great knowledge of which Items are selected in my ListBox.
I believe I understood your concern correctly. For the Evaluate method to have the knowledge of which Items has been selected, you can adopt the following strategy.
Add a boolean property in your Collection Type called IsSelected, which would help in tracking the items which are selected. For example,
public class Contact : PropertyChangedBase
{
public string Name { get; set; }
public string Info { get; set; }
public bool IsSelected { get; set; }
}
Now assuming your Collection is defined as following.
public ObservableCollection SCollection { get; set; } = new ObservableCollection();
You can filter the Selected items in Evaluate Method as following.
public void Evaluate()
{
var selected = SCollection.Where(x => x.IsSelected);
}
Update
You would need to Set the IsSelected Property to true during the selection in the List box. This can be done as following.
<ListBox x:Name="MainListBox" ItemsSource="{Binding SCollection}"
SelectionMode="Multiple"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
MaxHeight="300" MinHeight="200" MaxWidth="340" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Padding="3,5,5,5" />
<TextBlock Text="{Binding Path=Info}" FontWeight="SemiBold" Padding="3,5,5,5" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Example Screenshot
I have a listbox in the dataTemplate of an other listbox. I can get selected item of the outer listbox, but I've been trying to get selected item of the inner listbox (name: "ListBoxLetter"), no way ..
Here is my xaml :
<ListBox x:Name="ListBoxOut" ItemsSource="{Binding Letters}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Width="500" Height="60" Background="#16C8DB">
<TextBlock Text="{Binding Date}" />
</StackPanel>
<ListBox x:Name="ListBoxLetter" ItemsSource="{Binding CourriersListe}" SelectedItem="{Binding Selection, Mode=TwoWay}" >
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="SelectionChanged" >
<Command:EventToCommand Command="{Binding SelectionCommand}" CommandParameter="{Binding Selection}" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Date}" />
<TextBlock Text="{Binding Name}"/>
</StackPanel>
<TextBlock Text="{Binding Title}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>`
"Courriers" is an object of the following class :
public class MyClass
{
public DateTime Date { get; set; }
public List<LetterInfos> CourriersListe { get; set; }
}
And a LetterInfos has a Date, Name and Title.
Selection is a LetterInfos object, and I want to get it when I click on it in my list.
I'm working with mvvm light, so in my ViewModel constructor I have this :
SelectionCommand = new RelayCommand<LetterInfos>(OnSelectionElement);
I tried to move the interactivity paragraph in the outer listbox, but I can only get the MyClass selected item, and I want to select a LetterInfos item..
Anyone could help me ? Thanks !!
After many researches, I think that's not possible to get selectedItem in this situation.
But I found a good solution to this problem : the LongListSelector.
Even if its selectedItem is not bindable, there is a class to add that can make it bindable (to the parameter of a command) : Trouble binding LongListSelector.SelectedItem to MVVM property
Does anyone know of the correct way to add multiple sections of text to one listview item when using Windows 10 universal apps in C#? Items.subitems doesn't seem to work. Say my two string I want to display in a single list item are stored in...
public class listContent
{
public string heading { get; set; }
public string subHeading { get; set; }
}
Would doing something similar to this work?
listContent listItem = new listContent();
listItem.heading = "HEADING";
listItem.subHeading = "subheading";
lsvTransactions.Items.Add(listItem);
Regards
Nathan
Best way is to DataBind to a custom DataTemplate. Considering you already have lsvTransactions name ListView. Here is what you should do.
Create a List of listContent in your .cs file showed below
public class MainPage : Page
{
public List<listContent> ContentList {get; set;}
.....
Add Items to this ContentList in your code like you did above.
After adding items add the following line to point to data source.
lsvTransactions.DataContext = ContentList;
Create a ListView like shown below with DataTemplate
<ListView x:Name="lsvTransactions" ItemsSource={Binding}>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding heading}"/>
<TextBlock Text="{Binding subheading}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As it was said maybe if you give us more info on your code, we can help better. I post you here a sample of a Listbox (which is similar to the listview) with the definition of the ItemTemplate for the elements I use and how to bind the items to the listbox and the fields in the items to the elements put in the Listbox.
<ListBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=MeasureUnits, Mode=OneWay}"
SelectedItem="{Binding Path=SelectedMeasureUnit, Mode=TwoWay}"
SelectionMode="Single" Margin="0"
IsSynchronizedWithCurrentItem="True" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<WrapPanel>
<TextBlock Text="{Binding Path=ID}" Style="{StaticResource idStyle}" />
<TextBlock Text="{Binding Path=Description}" Style="{StaticResource desStyle}"/>
</WrapPanel>
<WrapPanel>
<TextBlock Text="{Binding Path=DestinationUnitsInSource}" Style="{StaticResource numStyle}" />
<TextBlock Text="{Binding Path=SourceUnitsInDestination}" Style="{StaticResource numStyle}" />
</WrapPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In my XAML:
<ListView x:Name="listView">
In my C#:
listView.Items.Add(item);
Where Item is an object with multiple text elements.
If you post code I can be more specific.
Trying to learn WPF and it's driving me nuts. So I'm trying to do something like the picture that I posted here. But I can only get the combobox, text, checkbox on top of each other and not side by side... How can I do this?
Also I figured out how to add "text" to the listbox if the user pushes a button, but I need it so that when they add text from a textbox. The combobox, checkbox, and button get added with it. But I have no idea how to do that.
I'm assuming I have to make a class for those things. But how do I do that if I'm coding it in XAML? This WPF is confusing for me.
<ListBox HorizontalAlignment="Left" Height="195" Margin="25,345,0,0" VerticalAlignment="Top" Width="650">
<ListBoxItem>
<StackPanel Orientation="Horizontal" Height="45"> <!--Stacks Items Horizontally-->
<ComboBox Width="100" Height="30">
<ComboBoxItem IsSelected="True">DirecTV</ComboBoxItem>
<ComboBoxItem>Hyundai</ComboBoxItem>
<ComboBoxItem>None</ComboBoxItem>
</ComboBox>
<TextBox Width="445" Height="30" Text="Follow RedZone on Twitter" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="True" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"></ScaleTransform>
</CheckBox.LayoutTransform>
</CheckBox>
<Button Content="Delete" Height="Auto" Width="Auto" HorizontalAlignment="Right" VerticalAlignment="Top" VerticalContentAlignment="Top"/>
</StackPanel>
</ListBoxItem>
</ListBox>
Define a class to hold the items
public class myListBoxRow
{
public string comboBoxSelection {get;set;}
public string textBlockText {get;set;}
public bool checkBoxChecked {get;set;}
}
Now define a ObservableCollection or List somewhere (typically in a ViewModel)
public ObservableCollection myListBoxRows<myListBoxRow> {get;set}
Then bind the ListBox's ItemsSource to your collection
<ListBox ItemsSource="{Binding myListBoxRows}" .../>
To get the controls you want, define an ItemTemplate for your ListBox
<ListBox ItemsSource="{Binding myListBoxRows}" ...>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding cboItems}" Width="50" SelectedItem="{Binding comboBoxSelection}" />
<TextBlock Text="{Binding textBlockText}"></TextBlock>
<CheckBox IsChecked="{Binding checkBoxChecked}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Research MVVM in WPF as there are tons of examples of this everywhere. The key part that will tie that together for you is the datatemplate for your listbox/listview