ComboBox displays a list of string wrong - c#

In XAML, I bound a ComboBox to a List of strings called Tags, which I have in my static class called Settings.
Here's XAML:
<Window x:Class="CSV_To_Tags_App.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:CSV_To_Tags_App"
Title="Window2" Height="435" Width="566">
<Grid>
<StackPanel Orientation="Horizontal" DataContext="x:Static loc:Settings">
<ItemsControl ItemsSource="{x:Static loc:Settings.Tags}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</Window>
An here's my Settings class:
public static class Settings
{
public static List<string> Tags = new List<string>() { "Header1", "Header2", "Header3", "Header4" };
}
So, I'd like to get a combobox which would display a list of Tags.
I'm using DataTemplate, because later I'll have to display a bigger list of objects and each of them will have ComboBox displayed next to it.
Instead I'm getting this:
I get four ComboBoxes and each of them contains letters of the tags I put in my list. So the first ComboBox has letters: H-e-a-d-d-e-r-1, the second has H-e-a-d-d-e-r-2, and so on.
I'd rather want to get one ComboBox containing all four tags.
How can I achieve that?

You don't need to use a StackPanel for this purpose. You just need one ComboBox and set it's ItemsSource. Like this:
<ComboBox ItemsSource="{x:Static loc:Settings.Tags}" VerticalAlignment="Top"/>
And if you want to use a DataTemplate you can use it like this:
<ComboBox ItemsSource="{x:Static loc:Settings.Tags}" VerticalAlignment="Top">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

You do not need an Items Control for this to work properly. Just a combobox is enough inside the StackPanel to work. Check below code :
<Grid>
<StackPanel Orientation="Horizontal" DataContext="x:Static loc:Settings">
<ComboBox VerticalAlignment="Top" ItemsSource="{x:Static loc:Settings.Tags}" />
</StackPanel>
</Grid>

Related

Multiple text items in List view item

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.

Unable to bind collection to ComboBox in silverlight

I've a ObservableCollection, when I want to display this ObservableCollection with CheckBox I am simply binding the contents to CheckBox but when I want to display the same collection by using ComboBox I am unable to do that. Any suggestions?
XAML: Display collection using CheckBox --WORKS
<ItemsControl ItemsSource="{Binding Synonyms}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Margin="0,5,0,0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--Display items in CheckBox-->
<CheckBox Content="{Binding Display}" Margin="10,0,0,0" /> // Display is the collection.
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Output:
XAML: Display collection using ComboBox --NOTHING OVER HERE
<ItemsControl ItemsSource="{Binding Synonyms}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Margin="0,5,0,0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--Display items in ComboBox.-->
Approach - 1
<ComboBox>
<ComboBoxItem Content="{Binding Display}"/>
</ComboBox>
Approach - 2
<ComboBox ItemsSource="{Binding Path=Synonyms}" DisplayMemberPath="Display"/>
Approach - 3
<ComboBox >
<ComboBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Green" BorderThickness="1" Padding="5">
<TextBlock Text="{Binding Path=Display,StringFormat='Display: {0}'}" />
</Border>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Output:
I want to display items(one,two,three, etc.) inside oneComboBox with Select All option. I've tried several approaches but nothing. What am I missing here?
The checkbox is not designed to hold multiple items unlike the Combobox so implementing a system designed for the checkbox is not relevant for the combobox.
To solve your issue, remove the combobox from the ItemsControl and have it stand on its own:
<ComboBox ItemsSource="{Binding Synonyms}" DisplayMemberPath="Display"/>
Which tells the combobox to bind its ItemsSource to the data context which is unspecified, which is fine, so it then gets it's parent's data context. That process works its way up to each parent until it finds a bound data context (most likely the page's datacontext to a VM instance).
Assuming that the data context is valid at some point in the visual tree, it will bind to that instance and look for a property named Synonyms. From the Synonyms property it will use that as a list to display items.
To show (display) text in the combobox (instead defaulting to the item's ToString()) the combobox will show the string from the item's property Display.
Giving a list of items in one drop down.
The short answer, is you should use a ComboBox as the root element, not ItemsControl. CompboBox is just a specialized version of ItemsControl.
<ComboBox ItemsSource="{Binding Synonyms}" DisplayMemberPath="Display"/>
The longer answer.
ComboBox derives from ItemsControl, so you get all the features the base class, plus additional features.
ItemsControl (and its derived classes) provides a way of repeating a set of data in the UI. The DataTemplate is where you specify what UI you want for each "row" of data in the Synonyms source.
What you are doing is asking Silverlight to create a separate ComboBox for each underlying data row.
You can still use a DataTemplate within the ComboBox. Like this.
<ComboBox ItemsSource="{Binding Synonyms}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--Display items in CheckBox-->
<TextBox Text="{Binding Display}"
Margin="10,0,0,0"
FontWeight="Bold" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How to bind properties of one ObservableCollection of ListView to properties of SelectedItem of another ListView?

So I have a few ListViews. The first is binded to ObservaleCollection<ComPort>. All properties of ComPort may take some predefined values. Other ListViews are responsible for that properties: they show all that possible (predefined) values and SelectedItem should be the current value of that property of ComPort from the first ObservaleCollection.
I can't attach images so here is an external picture, it would make the situation clean: http://i.stack.imgur.com/ZBRRx.png
<Window.Resources>
<ResourceDictionary x:Name="rd">
<l:ComPorts x:Key="vComPorts"/>
<l:SystemPorts x:Key="vSystemPorts"/>
<l:BaudRates x:Key="vBaudRate"/>
<l:Parities x:Key="vParities"/>
<l:DataBits x:Key="vDataBits"/>
<l:StopBits x:Key="vStopBits"/>
<l:Timeouts x:Key="vTimeouts"/>
<l:ComPort x:Key="vSelectedPort"/>
</ResourceDictionary>
</Window.Resources>
...
<ListView
Name="PortsList"
Grid.Row="1"
Grid.Column="0"
Margin="5"
VerticalAlignment="Stretch"
ItemsSource="{StaticResource vComPorts}"
DataContext="{StaticResource vComPorts}"
SelectedValuePath="PortName"
SelectedValue="{Binding ElementName=SystemPortsList, Path=SelectedItem.Value}"
SelectionChanged="PortsList_SelectionChanged"
MouseDoubleClick="PortsList_MouseDoubleClick">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox />
<TextBlock Margin="5,0,0,0" Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView
x:Name="SystemPortsList"
Margin="5"
VerticalAlignment="Stretch"
DataContext="{Binding Source={StaticResource vSelectedPort}}"
ItemsSource="{Binding Source={StaticResource vSystemPortsView}}"
SelectedItem="{Binding Source={StaticResource vSelectedPort}, Path=PortName}"
MouseEnter="SystemPortsList_Refresh"
MouseLeave="SystemPortsList_Refresh"
Grid.Row="1"
Grid.Column="1" SelectionChanged="SystemPortsList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Name="tb" Margin="5,0,0,0" Text="{Binding Path=Name}" />
</StackPanel>
</ListView.ItemTemplate>
</ListView>
I've tried to make an instance of class ComPort for saving current value of selected item from the first ListView, but anyway I can't cope with it without help. How this task should be solved?
1) Instead of handling SelectionChanged on the PortsList ListView, bind your checkbox to the ListViewItemsPanel like so:
<CheckBox IsChecked={Binding IsSelected, RelativeSource=Parent/>
2) Add an x:Name to your first ListBox, say x:Name="ComPortLB";
3) Remove DataContext on SystemPortsList;
4) Fix SelectedItem on SystemPortsList like so:
SelectedValue="{Binding ElementName=ComPortLB, Path=SelectedValue.PortName}"
I haven't tested any of this code and I haven't done this kind of stuff for a while, so I apologize for errors, but it should get you closer. I've also had to make some assumptions about your classes since you don't provide enough information.

Can't bind ObservableCollection to Combobox in wpf

I have the following xaml:
<UserControl.Resources>
<sivm:Locator x:Key="viewModelLocator" ModelType="{x:Type ViewModels:RateVSConcentrationViewModel}"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Path="ViewModel" Source="{StaticResource viewModelLocator}"/>
</UserControl.DataContext>
...
<ComboBox Grid.Column="0" Grid.Row="1" Height="20" VerticalAlignment="Top" ItemsSource="{Binding Chambers}" > <!--SelectedItem="{Binding SelectedChamber}">-->
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ChamberName}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Chambers is an ObservableCollection of objects that contains a property called ChamberName which I want displayed in the combobox.
In the ViewModel I have the following code:
foreach (var chamber in chambers)
{
Chambers.Add(chamber);
}
OnPropertyChanged(() => Chambers);
But when this code executes the combobox is not updated. I have used this way to do a lot of databinding but I can't get this to work.
Can someone see what I am doing wrong here?
You may need to set the relativesource on your textblock, try modifying the binding on the Text property of your textblock to the following:
{Binding DataContext.ChamberName, RelativeSource={RelativeSource AncestorType=ComboBox}}
And as nit said above, always check for binding errors, they will put you on the right path.
You should adjust the property binding as follows:
<ComboBox ItemsSource="{Binding Path=ViewModel.Chambers, Source={StaticResource viewModelLocator}}" >
I got it to work doing this:
<ComboBox DisplayMemberPath="ChamberName" Grid.Column="0" Grid.Row="1" Height="20" VerticalAlignment="Top" ItemsSource="{Binding Chambers}"> <!--SelectedItem="{Binding SelectedChamber}">-->

How to bind a ListBox item to a user control?

People use frequently something like:
<ListBox ItemsSource="{Binding ElementName=thisControl, Path=ListIndexes}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Path=IndexName}"/>
<Label Content="{Binding Path=IndexValue}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But I would like to use, instead of labels, a control, like this:
<ListBox ItemsSource="{Binding ElementName=thisControl, Path=ListIndexes}">
<ListBox.ItemTemplate>
<DataTemplate>
<local:Index Item="**{Binding}**"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My doubt is what to put into this Binding to include the whole item from the collection.
The syntax for this is:
<local:Index Item="{Binding}"/>
This will tell the data binding functions to bind the entire datacontext for each ListBox Item to the Item property in your Index control

Categories