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.
Related
Hi I am trying to add list items to an observable collection list.
I have a model where I setup a list property
public class DisplayList
{
public List<string> listItem { get; set; }
}
then on my main page I have an observable collection
private ObservableCollection<DisplayList> ListDisplay;
which I instantiate on page load
public MainPage()
{
this.InitializeComponent();
location = new ObservableCollection<storeLocations>();
ListDisplay = new ObservableCollection<DisplayList>();
// location = manager.getStoreLocations();
var dbList = db.Bales.Where(b => b.Location != null).Select(b => b.Location).ToList();
InitialLoad(dbList, null);
}
I am using suggestion boxes and want to filter results based on the selection made. The filtered results then display in a list on screen and this is where I am having a bit of trouble. I get it to display on screen, but it is displaying
System.Collection.Generic.List'1[S....... instead of the actual item in the list.
I am thinking I am not enumerating properly, but cant seem to pin point the error in my ways.
This is the method that is meant to populate the list based on selection of suggestion box.
public ObservableCollection<DisplayList>BaleList(List<string> CatNo)
{
foreach (var item in CatNo)
{
ListDisplay.Add(new DisplayList {listItem = CatNo.ToList()});
}
lstBales.IsItemClickEnabled = true;
return ListDisplay;
}
it takes in a parameter of type list which is gotten from the suggestion box. so the parameter value is basically what I want to display in the list on screen. e.g. CP1354-2 and second item CP1355-3 So those values come into the method. I want to apply those values to the observable collection as the listbox control is bound to the observable collection.
EDIT
adding binding in XAML
<ListView x:Name="lstBales" ItemsSource="{x:Bind ListDisplay}">
<ListView.ItemTemplate>
<DataTemplate x:Name="TemplateListName" x:DataType="data:DisplayList">
<Grid>
<TextBlock Text="{x:Bind listItem}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListDisplay.Add(new DisplayList {listItem = CatNo.ToList()});
and <TextBlock Text="{x:Bind listItem}"/>
You are binding a list to a TextBlock due to which ToString()is implicitly called and you don't get the actual values. According to your requirements, you can either change listItem to a string or create a nested ListView
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/
I'm stuck in this problem. I have a combobox in my application (created in code, not XAML); I have populated it with checkboxes, because I needed a drop-down control with checkboxes inside.
Now, I don't need the combobox selection, because it's meaningless. So I wanted to show, in the text part of the control, a label.
Is there a way to do this? Here is a minimal example:
myComboBox = new System.Windows.Controls.ComboBox();
foreach (var key in myDictionary.Keys)
{
System.Windows.Controls.CheckBox chk = new System.Windows.Controls.CheckBox();
chk.Content = key;
chk.SetBinding(System.Windows.Controls.CheckBox.IsCheckedProperty, new Binding() { Mode = BindingMode.TwoWay, Source = this, Path = new PropertyPath("myDictionary[" + key + "]") });
RoutedEventHandler ev = (sender, e) =>
{
// Do something when a checkbox is changed
};
chk.Checked += ev;
chk.Unchecked += ev;
myComboBox.Items.Add(chk);
}
This way if the user clicks on a checkbox the checkbox content is displayed in the text field.
I modified it adding also
myComboBox.SelectionChanged += (sender, jender) =>
{
myComboBox.SelectedItem = null;
};
This way no text is ever displayed. But.. What if I wanted to write a fixed string inside the text part of the combobox?
Thank you
Wow, this is a real pain. I assumed that it would be pretty simple but it turns out it isn't. I assumed that you could set a template for the content displayed in the combobox, and separately for the content displayed in the drop down list. You can, but you have to use a content selector:
How to display a different value for dropdown list values/selected item in a WPF ComboBox?
This is the proper way of doing it. However, are you just wanting a straight up static label/string displayed? If so, it's probably much, much easier to just overlay that over what you've already got in a grid like this:
<Grid>
<ComboBox x:Name="Checkbox" SelectionChanged="Checkbox_SelectionChanged">
<ComboBox.Items>
<CheckBox Content="Test1"/>
<CheckBox Content="Test2"/>
<CheckBox Content="Test3"/>
</ComboBox.Items>
</ComboBox>
<TextBlock IsHitTestVisible="False" Text="My Text" VerticalAlignment="Center" Margin="5"/>
</Grid>
Setting the textblock invisible to hit-tests means they're just passed down to the combobox:
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
I have a dataBinding ListBox in a Pivot section.
In another Pivot section i have a form to create new items for the ListBox.
When i add a new item to the ListBox i need to acces to the new ListBoxItem for find a TextBox control and modify the Text value, but
ListBoxItem lbItem = allItemsListBox.ItemContainerGenerator.ContainerFromIndex(itemIndex) as ListBoxItem;
Always returns null.
The problem seems to be that the ListBox is not visible, so the new ListBoxItem is virtual.
How can i resolve that?
Thanks.
Why not use data binding with DataTemplates instead of trying to modify the controls directly?
for example:
Code:
// Data binding class
public class Data
{
// Implement INofifyPropertyChanged
public string Text { get; set; }
}
// Code to bind it to Pivot
ObservableCollection<Data> list = new ObservableCollection<Data>();
// populate list
Pivot1.ItemsSource = list;
XAML:
<Pivot Name="Pivot1">
<Pivot.ItemTemplate>
<DataTemplate>
<TextBlock Text={Binding Text}" />
</DataTemplate>
</Pivot.ItemTemplate>
</Pivot>
Now, to change Text of a specific TextBlock, all you need to do is change a value of associated Data object to it from the list.