ListBox filled with binding doesn't select item on click - c#

I'm trying to use a ListBox to choose an entry and then display a picture belonging to this selected entry. But just at the beginning I got my first problem: filling the ListBox with binding is working, but if I click on one line in my running program, it doesn't select the line. I can just see the highlighted hover effect, but not select a line. Any ideas what my mistake could be?
This is my XAML:
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontSize="24"/>
And in MainWindow.xaml.cs I'm filling the ListBox with entries:
private void fillEntrySelectionListBox()
{
//Fill listBox with entries for active user
DataContext = this;
entryItems = new ObservableCollection<ComboBoxItem>();
foreach (HistoryEntry h in activeUser.History)
{
var cbItem = new ComboBoxItem();
cbItem.Content = h.toString();
entryItems.Add(cbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + activeUser.Id;
//show image matching the selected entry
if (activeUser.History != null)
{
int index = entrySelection.SelectedIndex;
if (index != -1 && index < activeUser.History.Count)
{
this.entryImage.Source = activeUser.History[index].Image;
}
}
}
So I can see my ListBox correctly filled, but not select anything - so I can't go on with loading the picture matching the selected entry.
I'm still quite new to programming, so any help would be great :)
EDIT: If someone takes a look at this thread later: here's the - quite obvious -solution
XAML now looks like this
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontFamily="Siemens sans" FontSize="24">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code behind to fill it:
//Fill listbox with entries for selected user
DataContext = this;
entryItems = new ObservableCollection<DataItem>();
foreach (HistoryEntry h in selectedUser.History)
{
var lbItem = new DataItem(h.toString());
entryItems.Add(lbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + selectedUser.Id;
And new Class DataItem:
class DataItem
{
private String text;
public DataItem(String s)
{
text = s;
}
public String Text
{
get
{
return text;
}
}
}

You are filling it with ComboBoxItem, which is not relevant to the ListBox, and also wrong by definition.
You need to have the ObservableCollection filled with data items.
Meaning, make a class that contains the data you want to store, and the ListBox will generate a ListBoxItem automatically per data item.
http://www.wpf-tutorial.com/list-controls/listbox-control/

Related

How to display multiple checked items in multiselect combobox in wpf?

My Xaml code
<ComboBox HorizontalContentAlignment="Left"
x:Name="Stat"
IsEditable="True"
Width="247"
HorizontalAlignment="Left"
IsReadOnly="True"
ItemsSource="{Binding OrderStatus,Mode=TwoWay}"
Text="{Binding StatusSelectedValue}"
Height="26">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Description}"
IsChecked="{Binding IsChecked}"
Checked="CheckBox_Checked"
Unchecked="CheckBox_Unchecked"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
xaml.cs
//I would like to update the text displayed on my multi-select combobox when items are checked or unchecked
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
var selectedItem = sender as CheckBox ;
var r= selectedNode.IsChecked.Value;
//trying to obtain value of all checked items and concatenate it and display in combobox text something similar like below
Stat.Text = String.Join(",",selectedItemValues.toArray());//this line of code is for example only for what i want to do
}
any help either mvvm way or xaml.cs way is greatly appreciated.
public void SetText()
{
if (this.SelectedItems != null)
{
StringBuilder displayText = new StringBuilder();
foreach (ComboItem s in comboItemsCollection)
{
if (s.IsSelected == true && s.Title == Properties.Resources.CHECKALL)
{
displayText = new StringBuilder();
displayText.Append("All");
break;
}
else if (s.IsSelected == true && s.Title != Properties.Resources.CHECKALL)
{
displayText.Append(s.Title);
displayText.Append(',');
}
}
this.Text = displayText.ToString().TrimEnd(new char[] { ',' });
}
// set DefaultText if nothing else selected
if (string.IsNullOrEmpty(this.Text))
{
this.Text = this.DefaultText;
}
}
This is what i did. It display all the selected items with a ";" as a separator. If you have an "All" checkbox or you select all, it just display All. Of course i don't know what object you are using so i left my code as it is (you need to change the loop part, in particular the ComboItem part)
Note that this is a function (of course), so you can either add directly the code where you are doing the String.Join, or you call it

Add textblock text to favorite list on button click

I have two pages: the first is mainpage.xaml and the second is favoriteslist.xaml.
In mainpage.xaml I have a text block, which shows some dynamic text automatically.
And I have a button also on mainpage.xaml.
From which I want when I click on that button, text appears on text block should go to favorite list in favoriteslist.xaml page.
If text already favorite, which text appears on text block should be removed from favorite list on button click.
So finally I need help to implement this functionality textblock which shows dynamically already created but I only need to know how to develop add to favorite functionality.
Textblock:
<TextBlock x:Name="StringTextBlock" Text="" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />
Button:
<Button Grid.Row="2" x:Name="AddToFavoritesButton"
Content="Add" Style="{StaticResource ButtonStyle2}" Margin="2"
Click="AddToFavoritesButton_Click"/>
C#
private void AddToFavoritesButton_Click(object sender, RoutedEventArgs e)
{
}
Listbox:
<ListBox x:Name="FavoriteListBox" />
I would use IsolatedStorageSettings to store the list and compare the dynamic text to the list in the isolatedstoragesettings upon button click. Then on FavouritesList page, set itemsource of the listbox to the list in IsolatedStorageSettings.So here are the steps to be followed:
1. Create a model/class to set the dynamic text being shown on the text block
public class favourites
{
public string myText { get; set; }
}
2. In the button click event on MainPage.xaml.cs, first set the dynamic text (where ever you are getting it from) to the text block if you need to and then create the list and/or compare
private void AddToFavoritesButton_Click(object sender, RoutedEventArgs e)
{
//your dynamic text set to textblock
StringTextBlock.Text = myDynamicText;
//Set value of your text to member variable of the model/class
favourites f = new favourites();
f.myText = myDynamicText;
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
/*Check if "FavouritesList" key is present in IsolatedStorageSettings
which means already a list had been added. If yes, retrieve the
list, compare each item with your dynamic text, add or remove
accordingly and replace the new list in IsolatedStorageSettings
with same key. */
if (settings.Contains("FavouritesList"))
{
List<favourites> l = (List<favourites>)settings["FavouritesList"];
for(int i = 0; i <= l.Count()-1; i++)
{
if (l[i].Equals(myDynamicText))
{
l.RemoveAt(i);
settings["FavouritesList"] = l;
}
else
{
l.Add(f);
settings["FavouritesList"] = l;
}
}
}
//If no key in IsolatedStorageSettings means no data has been added
//in list and IsolatedStorageSettings. So add new data
else
{
List<favourites> l = new List<favourites>();
l.Add(f);
settings["FavouritesList"] = l;
}
settings.Save();
}
Now all that is left is show the always updated list in the FavouritesList Page. I added a 'NoData' textblock that should be visible when there is nothing in the list. Else the list will be displayed.
In FavouritesList.xaml
<ListBox x:Name="FavoriteListBox" Visibility="Collapsed">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding myText}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Name="NoData"
Text="No Data"
Visibility="Collapsed"
Width="50"
Height="50"/>
In FavouritesList.xaml.cs
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("FavouritesList"))
{
List<favourites> l = (List<favourites>)settings["FavouritesList"];
if(l.Count!= 0)
{
NoData.Visibility = System.Windows.Visibility.Collapsed;
FavoriteListBox.Visibility = System.Windows.Visibility.Visible;
FavoriteListBox.ItemsSource = l;
}
}
else
{
FavoriteListBox.Visibility = System.Windows.Visibility.Collapsed;
NoData.Visibility = System.Windows.Visibility.Visible;
}
I have not tested this but should definitely work. Hope it helps!

Listbox databinding NewItemPlaceholder

I have an observable collection bound to a list box.
The collection has 2 items, but the list box is showing 3 items (e.g. the 2 items that are actually in the observable collection and an additional item for the NewItemPlaceholder.
I want it only to show the 2 items.
Below is my XAML.
<ListBox MinHeight="20" MinWidth="20" Name="MultipleSelectionsMultipleWagersListBox" Visibility="{Binding Path=Coupon.BarcodeText, Converter={StaticResource CouponBarcodeToVisibilityConverter1}, ConverterParameter=994450_994550}" Height="AUto" Width="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="5"
ItemsSource="{Binding Path=BetViewModels}" Grid.Row="1" Grid.Column="1" >
<ListBox.ItemTemplate>
<DataTemplate>
<View:BetView DataContext="{Binding}" Name="ThisBet" Margin="5"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here is the c#
private ObservableCollection<BetViewModel> _betViewModels = new ObservableCollection<BetViewModel>();
public ObservableCollection<BetViewModel> BetViewModels
{
get { return _betViewModels; }
set
{
if (Equals(value, _betViewModels)) return;
_betViewModels = value;
OnPropertyChanged("BetViewModels");
}
}
Here is the code to populate the betViewModels:
var betViewModel = new BetViewModel { Bet = new Bet() };
betViewModel.Bet.SelectionName = "Chelsea";
betViewModel.Bet.Price = "4/9";
betViewModel.Bet.Market = "90 Minutes";
betViewModel.Bet.ExpectedOdd = DateTime.Now;
BetViewModels.Add(betViewModel);
betViewModel = new BetViewModel { Bet = new Bet() };
betViewModel.Bet.SelectionName = "Chelsea";
betViewModel.Bet.Price = "4/9";
betViewModel.Bet.Market = "90 Minutes";
betViewModel.Bet.ExpectedOdd = DateTime.Now;
BetViewModels.Add(betViewModel);
How Do I switch of this from showing the additional item for the new item place
Here is an image of it displaying the placeholder
The DataGrid supports adding new rows, which have to start out blank. If your ItemsSource is bound to both a ListBox/ItemsControl and a DataGrid, you need to set the DataGrid 'CanUserAddRows' property to 'False'.
Where I found the answer: http://www.mindstick.com/Forum/1519/How%20do%20I%20remove%20a%20listbox%20new%20item%20placeholder
There's nothing in your code that should be adding an extra empty item. There may be some other code adding to BetViewModels or there may be a change happening to the generated ICollectionView for the collection if you have it bound to something else that you're not showing, like an editable DataGrid.
did your sample code also provide this issue?
how much items contains your _betViewModels.count in debugging there are really only 2 Items?
it seems you added an empty BetViewModel at the End
i would suggest check your logic which provides populates your items
if it is a loop it should (counter<yourDatasource.Count) just for example

WPF/C# Combobox Only Changes Selection When A Click is Detected Outside of Text Area

So I have several comboboxes in my WPF application that don't change the selection when a user clicks on the text of a combobox item. In order to select a particular item you have to click to the right or left of the text. I have another combobox that selects just fine when the text is clicked. The only difference between the two is databinding. The comboboxes that don't select when the text is clicked are databound to an ObservableCollection of one type or another. The combobox that works has manually inserted, static values.
I've searched the issue extensively and I can't seem to find anyone else who has had this issue or anything remotely similar. I'm not setting any weird properties.
Here is the code for one of the problematic comboboxes:
<ComboBox HorizontalAlignment="Left" Margin="40,160,0,0" VerticalAlignment="Top" Width="132" ItemsSource="{Binding Path=Systems}" SelectedItem="{Binding Path=System}" SelectedIndex="0">
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem Content="{Binding Path=Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Here is a video of the behavior:
http://www.youtube.com/watch?v=D0r1N1ghw-k
enter code hereSuppose my Combobox is defind as below
<ComboBox Name="cmb" Width="200" Height="20" DisplayMemberPath="PersonName" SelectedValuePath="PersonID">
</ComboBox>
please notice , i have removed the itemtemplate part
and my model is as below
public class Person
{
public string PersonName { get; set; }
public string PersonID { get; set; }
}
And my binding is in code behind , this step is not necessary , you can do it in the xaml , iam just checking quickly so much dirty code
public List<Person> source = new List<Person>();
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 20; i++)
{
source.Add(new Person() { PersonID = i.ToString(), PersonName = "Sau" + i.ToString() });
}
cmb.ItemsSource = source;
this.DataContext = this;
}
so if you run this sample , you will see you can select the value when you click on the text itself.
it's content property which causes some problem but i am not 100% sure on this.

WPF Listbox with checkboxes appearing blank, added dynamically

I'm trying to populate a listbox with a series checkbox entries, however once running the code below the listbox has blank entries in it, which are selectable, i.e. a blue bar appears. However neither the text or checkbox appears.
for (int num = 1; num <= 10; num++)
{
CheckBox checkBox = new CheckBox();
checkBox.Text = "sheet" + num.ToString();
checkBox.Name = "checkbox" + num.ToString();
thelistbox.Items.Add(checkBox);
}
The best way to handle this is to create a list of data -- in your case, a list of numbers (or a list of strings (sheet1, sheet2, etc). You can then assign that list of numbers to thelistbox.ItemsSource. Inside the XAML of your listbox, set the ItemTemplate to include a CheckBox and bind the number to the text of the checkbox.
Try changing
checkBox.Text = "sheet" + num.ToString();
to
checkBox.Content = "sheet" + num.ToString();
With that change, I was able to use your example successfully.
To follow up on Brian's comment, here is an outline of a simple checkbox list in C# wpf. This will need more code to handle checking/unchecking boxes and general post-interaction handlers. This setup presents the difference in elements on two lists of objects (defined elsewhere) in a checkbox list.
The XAML
...
<ListBox Name="MissingNamesList" ItemsSource="{Binding TheMissingChildren}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox Content="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
...
The supporting C# code:
...
public partial class MissingNamesWindow : Window
{
// Make this accessible from just about anywhere
public ObservableCollection<ChildName> TheMissingChildren { get; set; }
public MissingNamesWindow()
{
// Build our collection so we can bind to it later
FindMissingChildren();
InitializeComponent();
// Set our datacontext for this window to stuff that lives here
DataContext = this;
}
private void FindMissingChildren()
{
// Initialize our observable collection
TheMissingChildren = new ObservableCollection<ChildName>();
// Build our list of objects on list A but not B
List<ChildName> names = new List<ChildName>(MainWindow.ChildNamesFromDB.Except(
MainWindow.ChildNamesFromDisk).ToList());
// Build observable collection from out unique list of objects
foreach (var name in names)
{
TheMissingChildren.Add(name);
}
}
}
...
Hope that clarifies a bit.

Categories