Select only one item in two ListViews - c#

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.

Related

Nesting databound controls inside a WPF TreeView

Trying to build a WPF TreeView control which can contain another data bound control inside it. Here's the XAML:
<TreeView temsSource="{Binding DocumentCategories}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding DocumentCategory1}">
<TextBlock FontWeight="Bold" Text="{Binding Description}"></TextBlock>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Documents}">
<TextBlock FontWeight="Bold" Text="{Binding Name}"></TextBlock>
</ListView>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The DocumentCategories data is recursive - each item in the list has a DocumentCategory1 collection of DocumentCategories which has its own DocumentCategory1 collection and so forth.
Without the ListView inside it, this works just fine. However, when you add the ListView the TreeView renders ok but when you try and open one of the nodes, the application crashes with the error:
Operation is not valid while ItemsSource is in use. Access and modify
elements with ItemsControl.ItemsSource instead
I'm not entirely sure which ItemsSource this is referring to - that of the TreeView or the ListView. I presume the latter, and that the problem is being caused by the fact that the binding isn't actually happening until after the node is opened.
I've tried changing both DocumentCateegories and Documents from List to an ObservableCollection, which seems to be a common fix for this error - but it still behaves the same.
Is it possible to have another databound control inside a TreeView, and if so, how?
There is the DataTemplate of the ListView missing.
Currently the following Element is interpreted as an actual ListView Element:
<TextBlock FontWeight="Bold" Text="{Binding Name}"></TextBlock>
And as you already bound the ListView's ItemSource the error occurs, when the view is trying to add the "TextBlock" as an item of the ListView.
Just change it to the following:
<ListView ItemsSource="{Binding Documents}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding Name}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

WPF fill Listbox with collection member property

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>

How do I bind a WPF ListView to a property of each element in a list?

I have the following binding on my ListView, which works fine:
<ListView ItemsSource="{Binding Filters}" Margin="5" Name="FiltersList" Height="100"/>
Filters is actually a type of List<LogFilter>. LogFilters have a property on them called Title. I would like to show the Title of each element in the Filters list in my ListView instead. Is this possible? Something like ItemsSource="{Binding Filters.Title}"?
Just set the ItemTemplate to display the title:
<ListView ItemsSource="{Binding Filters}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It seems to me that you don't need to use ListView at all. For your needs ListBox with DisplayMemberPath would be enough:
<ListBox ItemsSource="{Binding Filters}" DisplayMemberPath="Title"/>

Binding SelectedIndex to a different Collection then the Collection of the itemsSource

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}}">

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