Hi I am developing an application for WinRT with MVVM-light. What i am trying to do is fill a combobox with items, for example 4 kinds of fruit. And my SelectedItem should be the first kind of fruit to which the combobox is bound. This works but, the next step is that i want to make the selectedIndex change. For example when The first kind of fruit is sold out then the SelectedIndex should automattically change to the second item in the Collection Of my Combobox.
So if you would want to buy 10 pieces of fruit you would get 10 comboboxes on your screen in which you can select the kind of fruit, when you have selected an apple in 4 of them and there are no apples anymore then the selectedindex of the other comboboxes should change to the second kind of fruit.
I know it is a bit of a confusing question.
Basically what i need is to be able to bind my Selectedindex to a property in a Collection that is different from the Collection of my combobox. I will give you a bit of xaml that will hopefully explain a bit more:
</ListView>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel IsHitTestVisible="{Binding HitTest}" Orientation="Horizontal">
<TextBlock Text="{Binding Day, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:dd MMM yyyy}' }"></TextBlock>
<ComboBox Width="196" ItemsSource="{Binding Path=FruitKind.FruitList, Source={StaticResource Locator}}" SelectedIndex="{Binding Path=FruitKind.FruitComboBoxItem, Source={StaticResource Locator}, ElementName={Binding Path=FruitIndex}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FruitKind}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I'm not sure if this is possible by the way.
thnx
Bind to the selected item instead of index. THis allows you to work with a object/property of the viewmodel that you can modify any way you want:
ie:
<ComboBox Width="196" ItemsSource="{Binding Path=FruitKind.FruitList, Source={StaticResource Locator}}" SelectedItem="{Binding Path=FruitKind.FruitObject, Source={StaticResource Locator}, ElementName={Binding Path=FruitIndex}}">
Related
I have a combobox, in which I bind my model. I use DataTemplate to display the data
<ComboBox x:Name="comboBoxShift">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShiftId}" Visibility="Hidden"/>
<TextBlock Text="{Binding ShiftType}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And bind it with comboBoxShift.ItemsSource = _db.Shifts.ToList();, where _db is my database context.
From another window I pass ShiftId.
How can I set current item of combobox to display ShiftType.
I believe your design is a bit flawed. You don't need to use a data template for your purpose, but rather just set the DisplayMemeberPath.
XAML
<ComboBox x:Name="comboBoxShift" DisplayMemberPath="ShiftType">
Then to select from code
comboBoxShift.SelectedItem = My_Shift;
Note: If you wanted to get the Shift object from the selected combobox item, here's how you would do that as well.
Shift shift = (Shift)comboBoxShift.SelectedItem;
Since you are hiding one of the TextBlocks, this will give your desired result:
<ComboBox x:Name="comboBoxShift" DisplayMemberPath="ShiftType">
</ComboBox>
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>
I have a ListBox inside a HubSection, whose Items are bound to a class "players" added to my DefaulViewModel via code behind.
First I simply put a TextBox bound to the property "PlayerName" of my class "players".
Now I would like to add a ComboBox with some items that are NOT part of the class players.
Is it possible ? I thought that definind an ItemsSource in the ComboBox would sort of override the ItemsSource of the ListBox, but nothing displays.
The DataContext of the whole page is defined like so:
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
Then the HubSection is like so:
<HubSection x:Name="HubSec1">
<DataTemplate>
<ListBox x:Name="ListBox1" ItemsSource="{Binding players}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Path=PlayerName, Mode=TwoWay}"/>
<ComboBox ItemsSource="{Binding Path=ListOfElements}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</HubSection>
If I define the ComboBox in the same way but outside the ListBox, it will display the string elements of "ListOfElements" properly.
But in this ListBox, the ComboBox is empty. So my guess is that having defined an ItemsSource for the ListBox, it is not possible to override it.
I have tried to define a DataTemplate but was not successful doing so, but it might be the good solution (and I did not proceed properly)
What am I missing ?
Edit :
The ComboBox items is an ObservableCollection. It is not part of the "players" class.
Here is how I added these elements to the DefaultViewModel
DefaultViewModel.Add("players", players);
DefaultViewModel.Add("MyItemsList", ListOfElements);
You can walk up the visual tree and bind to an ancestors datacontext:
{Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
EX:
{Binding Path=ListOfItems, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}
that should give you the datacontext that the listbox has, so assuming your ListOfItems exists in that data context.
Or you can name your control, and then bind to its datacontext by element name:
{Binding ElementName=mySourceElement,Path=ListOfItems}
It can be a little bit tricky to create a good working binding in Windows Apps. A widely used work around is to use the Tag property.
<ListBox x:Name="ListBox1" ItemsSource="{Binding players}" Margin="0,184,0,0" Tag="{Binding Path=ListOfElements}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Path=PlayerName, Mode=TwoWay}"/>
<TextBox Text="{Binding Path=Tag, ElementName=ListBox1}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
A binding to an element wirh the specific name will work always. And the ListOfElements should be in the scope of the ListBox so you can use the Tag property as a proxy. If you need to bind more than one property, you can also use dummy XAML elements:
<Border Tag="{Binding ...}" Name="dummy1"/>
I have two ListView, each bound to a specific collection in my ViewModel and I want to be able to select only one item globally.
Each ListView has its SelectedItem property bound to the same property in the ViewModel.
My probleme is as follow: when I select an item in a ListView, and then select another item in the other ListView, the first item stays selected.
I could achieve this with some code-behind, but I want to know if a pure XAML solution exists.
XAML:
<ListView SelectionMode="Single" ItemsSource="{Binding Path=MyList1}" SelectedItem="{Binding Path=MySelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView SelectionMode="Single" ItemsSource="{Binding Path=MyList2}" SelectedItem="{Binding Path=MySelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I finally got it working, by just replacing SelectedItem by SelectedValue.
In this use case, both properties have the same behaviour, but the latter one handles correctly the unselection if the bound selected item is not in the list.
You need to use Mode=TwoWay in your SelectedItem. It should work.
In my C# windows phone app, I create a binding to bind a list of string to ItemsControl.
// MyCollections is a List<string>
<ItemsControl x:Name="ContentRoot" ItemsSource="{Binding MyCollections}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding }" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
It works. But My question is how can I add my own item (e.g. 'Click to add more') to this ItemsControl after it is binded?
There are two answers to this question:
Use an ObservableCollection instead of a List, as it will notify the UI when items are added/removed from it. Then you just add your new item to the list in the view model.
Use a CompositeCollection so you can have the "additional" item without modifying the actual collection.
Normally you would do 1, but since you want a "Click to add more" type of option, CompositeCollection is probably the way to go.
Since you metioned windows phone (but tagged WPF) you may want to look at this post for how to write your own CompositeCollection object: how to do a CompositeCollection in WP8?
Use CompositeCollection to add additional items in your XAML. This should work:
<StackPanel x:Name="stackPanel">
<StackPanel.Resources>
<CompositeCollection x:Key="myCollection">
<CollectionContainer Collection="{Binding DataContext.MyCollections,
Source={x:Reference stackPanel}}"/>
<ContentControl Content="Click to add more"/>
</CompositeCollection>
</StackPanel.Resources>
<ItemsControl x:Name="ContentRoot"
ItemsSource="{StaticResource myCollection}"/>
</StackPanel>