I'm trying to bind data to a combo box. The data is names from a table from database. Getting the data from the database works fine as I have tried to bind it to a List View and it displays fine. My problem is binding it to a combo box, it doesn't show anything.
Can anyone see where I have went wrong?
My code is the following...
public string FullName
{
get
{
return String.Format("{0} {1}", _customer.ContactFirstName, _customer.ContactLastName);
}
}
and the XAML is
<ComboBox x:Name="comboBox" Grid.Row="1" Grid.ColumnSpan="2" Height="20" ItemsSource="{Binding Path=FullName}" >
The XAML for it working with a list view is the following..
<ListView
AlternationCount="2"
DataContext="{StaticResource WorkorderGroups}"
ItemContainerStyle="{StaticResource WorkorderItemStyle}"
ItemsSource="{Binding}"
Grid.Row="2" Grid.ColumnSpan="3" Margin="1,0,-1,0>
<ListView.GroupStyle>
<StaticResourceExtension ResourceKey="WorkorderGroupStyle/>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=FullName}" />
</GridView>
</ListView.View>
</ListView>
You cannot Bind a string to ComboBox. You need to bind some collection like List<T> or ObservableCollection<T> to combobox ItemsSource. Possible Duplicate.
Refer the link.
Need SIMPLE working example of setting WPF MVVM ComboBox ItemsSource based on SelectedValue of second ComboBox
Related
I am working on list of Recipes showed in some sort of list in my WPF app.
I have a collection of recipes
public Cookbook()
{
RecipeList=new ObservableCollection<Recipe>();
AddRecipe(new Recipe("Food1", 0, null));
}
each recipe has property called Name.public string Name { get; set; }
What i am doing now is that i populate list with this collection
<ListView x:Name="CategoriesListBox" Margin="10,0,10,0" ItemsSource="{Binding RecipeList}"
Loaded="CategoriesListBox_OnLoaded"
SelectionChanged="CategoriesListBox_SelectionChanged">
<ListBox.DataContext>
<Implementation:Cookbook/>
</ListBox.DataContext>
</ListView>
Which of course results into list populated with object names - i want recipe names in the list. Is there any way to show property Name in Listbox instead?
(I am looking for XAML solution - no code behind)
// I already tried ListView and nested Gridview as a solution - this works but this also creates unnecesary grid and header fields on the top.
<ListView x:Name="CategoriesListBox" Margin="10,0,10,0" ItemsSource="{Binding RecipeList}"
Loaded="CategoriesListBox_OnLoaded"
SelectionChanged="CategoriesListBox_SelectionChanged">
<ListBox.DataContext>
<Implementation:Cookbook/>
</ListBox.DataContext>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name, Mode=OneWay}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Thanks
Use the DisplayMemberPath property of the ListView.
Set it to Name
DisplayMemberPath="Name"
https://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.displaymemberpath(v=vs.110).aspx
Use a ListBox instead of a ListView, and set its DisplayMemberPath property:
<ListBox ItemsSource="{Binding RecipeList}" DisplayMemberPath="Name" .../>
Or set its ItemTemplate property:
<ListBox ItemsSource="{Binding RecipeList}" ...>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have an WPF application with this XAML...
<ListView
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ItemsSource="{Binding HTMLControlNames}">
<ListView.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"></Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The bindings are correct and there is data in the ObservableCollection property that implements INPC.
I added the Expression Dark Theme which is also working but this is the output from the markup above:
The buttons are there, they just aren't showing the text... BTW the number of buttons is equal to the count of items in the collection.
Here's the property in the ViewModel, single stepping shows me there are items (the proper ones) in the collection.
public ObservableCollection<ControlName> HTMLControlNames
{
get { return _HTMLControlNames; }
set
{
_HTMLControlNames = value;
PropChanged("HTMLControlNames");
}
}
Lastly the ControlName Class:
public class ControlName
{
public string Name { get; set; }
}
If I don't use ExpressionDark.xaml the content shows up!
Here's more information: Top part of the control shows up ok...
If I don't use DataTemplate as in the top half of this control the buttons are fine.
Here's the default Control Template (just a grid with a content presenter)..
What you are seeing that you think is a button in the ListView control is actually the header area. You can see this more clearly by adding columns to the header:
<ListView.View>
<GridView>
<GridViewColumn Header="Test" />
</GridView>
</ListView.View>
The list view items are actually the thin lighter-grey strips below this header.
I've not had much experience in templating list views (I usually use list boxes), but in the theme you are using, the list view seems to be templated in such a way that it basically ignores the item template. You can see that it does by using a daft template like this:
<ListView.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Orange" Width="20" Height="20" />
</DataTemplate>
</ListView.ItemTemplate>
You will see that no orange rectangles appear in the list view, even when the collection that you bind to has elements in it.
I'm not quite sure how you can get around this problem. Maybe someone with more experience of templating list view controls can chime in.
Thanks to Stephen this is the solution so far:
<ListView.View>
<GridView>
<GridViewColumn x:Name="xHtmlControlcol"
Header="Filter For:"
Width="{Binding ActualWidth,
ElementName=XListView,
Mode=OneWay}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Width="{Binding ActualWidth,
ElementName =XListView,
Mode=OneWay}" BorderThickness="1,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
It produces this: Note that there's still one small issue with the left margin which I don't know how to fix right now.
The Trick to this is that when using Data Binding:
Use the ItemsSource to bind to collection of ListView
Use the ListView.View as shown above to set up a GridViewColumn.
Use the GridViewColumn.CellTemplate to inject the control type you want.
Make sure the injected control is bound to the proper Content path name.
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.
Is there to set the index of a ComBox which is in a DataGrid from code? The ComboBox in silverlight should be added to the DataGrid using a DataGridColumnTemplate so the the SetValue() method won't work because it points to the template not the combobox. On the other hand, I can't just name the ComboBox and set it's selected index because it is one object and changes will then apply on all the ComboBoxes in the table.
XAML Sample Code:
<sdk:DataGrid x:Name="DG" HorizontalAlignment="Left" Height="421" Margin="10,58,0,0" VerticalAlignment="Top" Width="680" ColumnWidth="*" AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Test">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="CB" >
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
....
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
You should use Bindings for this
Say you have a collection of items like the following bound to the ItemsSource of the DataGrid
public class GridItem
{
public int IndexOfSelectedItem { get; set; }
}
The SelectedIndex of your ComboBox could then be set like this:
<ComboBox SelectedIndex="{Binding IndexOfSelectedItem, Mode=TwoWay}"
I have class like the following:
class test
{
public string Name;
public string Location;
}
Through a result of query using entity framework I am getting back a collection of test objects which I am directly setting to my listbox. But using the DisplayMemberPath Iam just displaying Name value. So now the listbox is holding the whole collection of test objects but just displaying Name value.
When I am trying to bind to the selecteditem of the list box Iam getting the whole test object as a string but I just need Name value in the selecteditem result.
My XAML is as follows:
<ListBox x:Name="lbSubSelector" Height="200" DisplayMemberPath="Name" SelectedItem="{Binding Name, Mode=TwoWay}" />
My code to populate list is as follows:
LoadOperation<test> subLoadOp = context.Load(context.GetTestQuery());
lbSubSelector.ItemsSource = subLoadOp.Entities;
lbSubDistrictSelector.DataContext = SkillModel.Instance;
The DataContext to which the selectedItem is set to is having a value of the whole string representation of test object but I want the selecteditem to just return Name value as it is displaying (as i have set the displaymemberpath to Name) instead of returned the whole object in string format.
How can I achieve this?
Use following:
<ListBox x:Name="lbSubSelector" Height="200" DisplayMemberPath="Name" SelectedValuePath="#Name" />
Then you can use lbSubSelector.SelectedValue to get Name property of selected item.
see:
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selectedvaluepath.aspx
Please use the IsSynchronizedWithCurrentItem property on the Listbox and change the SelectedItem binding to /Name in xaml code as follows:
<ListBox x:Name="lbSubSelector" Height="200" DisplayMemberPath="Name" SelectedItem="{Binding /Name, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True"/>
Rather than Using ListBox, I would suggest you using the ListView with GridColumns. Following is the snippet, you might need to remodify it accordingly. But this surely will work the way you want it to :-
<ListView Name="ListView1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding}" MouseDoubleClick="transactionListView_MouseDoubleClick" IsSynchronizedWithCurrentItem="True" >
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource gridViewHeaderColumnStyle}">
<GridView.Columns>
<GridViewColumn Width="70" Header="Name" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Width="270" Header="Seller" DisplayMemberBinding="{Binding Path=Location}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>