I have the following code in a Windows metro app, I confirmed that SelectedPerson is updating and is properly bound, but the item will not be highlighted unless you click on it.
<ListView x:Name="HeaderFlyoutListView" Padding="0" Margin="0"
ItemsSource="{Binding People}" SelectionMode="Single"
SelectedItem="{Binding SelectedPerson, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
did you setup your item template?
What you can do is - Define a SolidColorBrush Property and bind this property to your Item Grid. and then when you select an item, make sure that property change too
Related
I have a situation with a ListView. Inside the item template there is a DataTemplate and inside the DataTemplate there is a ListViewItem and it's content is bound. When I click I want to select the item but when I hover my mouse over it, it seems like there is a button created with the ItemTemplate and DataTemplate . At the moment, I can select item by clicking somewhere else within the same row, but that doesn't work if I select the button. I use SelectedItem and if you click on the button within the item, the SelectedItem will not fired.
The ListView is linked to an ItemSource, and SelectedItem of the ListView is bound to a property
Further information: language is C#, ide is Visual Studio 2010.
I will leave my xaml code below, Thanks.
XAML
<ListView x:Name="myListView"
Grid.Column="0"
Grid.Row="2"
Height="Auto"
Margin="0,0,0,0"
SelectionChanged="SchemaListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem Content="{Binding Path=Value}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
void ReadData(string id)
{
var data = ExampleData.GetData(id);
myListView.ItemsSource = data.Results;
}
I've tried binding without ItemTemplate and DataTemplate also tried to link source in xaml but that didn't work
You must not have a ListViewItem in the ItemTemplate of a ListView.
When the elements of the ItemsSource collection are not already ListViewItems (which they typically never are), the framework will automatically create a ListViewItem that becomes the "item container" element for each data item. This automatically generated ListViewItem uses the ItemTemplate as its ContentTemplate.
Besides that, use a ListBox instead of ListView when you do not set a ListView's View property.
So instead of a ListViewItem, use a ContentControl or perhaps a TextBlock:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If there is nothing more than a single content element, simply set the DisplayMemberPath property:
<ListBox ... DisplayMemberPath="Value"/>
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.
I try to bind a selected item in my datagrid to some textboxes.
Sadly the textboxes wont be updated on change.
If you need more Informations fell free to ask.
In my view i try to bind the the data of the selected Item of the Datagrid to the Textboxes.
in the Textboxes there can be a new employee you want to add or one of the Datagrid that you want to edit.
<TextBox Name="TxtName" Text="{Binding Employee.LastName}" Grid.Column="1" Grid.Row="0"></TextBox>
<TextBox Name="TxtFirstName" Text="{Binding Employee.FirstName}" Grid.Column="3" Grid.Row="0"></TextBox>
<TextBox Name="TxtDateOfBirth" Text="{Binding Employee.DateOfBirth, StringFormat=d}" Grid.Column="1" Grid.Row="1"></TextBox>
<ComboBox Name="CmbGender" SelectedItem="{Binding Employee.Gender}" ItemsSource="{Binding Genders}" DisplayMemberPath="Short" Grid.Column="3" Grid.Row="1"/>
<DataGrid Name="GrdAllEmployees" ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee}" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="4" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChanged}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
In my ViewModel i set the Value of the Selected Employee to the Employee that is shown in the Textboxes and raise the Events for both.
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set
{
_selectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
_employee = _selectedEmployee;
NotifyPropertyChanged("Employee");
}
}
After this the values are correct on debugging. but the view will not be updated.
There is a much simpler way of displaying values from the selected item of the DataGrid, or in fact any collection control in WPF. That is to use the Selector.IsSynchronizedWithCurrentItem property. When you set this to true, then you can reference the selected item from that collection using the / notation, which means the current item. Try something like this:
<StackPanel>
<DataGrid ItemsSource="{Binding Employees}" IsSynchronizedWithCurrentItem="True" />
<TextBlock Text="{Binding Employees/Name}" />
</StackPanel>
This would display the Name property value from the currently selected item in the DataGrid. Further information... from the Binding.Path Property page on MSDN:
When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.
Property names and slashes can be combined to traverse properties that are collections. For example, Path=/Offices/ManagerName specifies the current item of the source collection, which contains an Offices property that is also a collection. Its current item is an object that contains a ManagerName property.
It worked for me after i replaced my own classes for the RelayCommand and ViewModelBase with the ones of MVVMlight, that i downloaded from nuget.
https://mvvmlight.codeplex.com/
I just had to change the NotifyPropertyChanged with RaisePropertyChanged.
But also thanks to #Sheridan for his advice.
I defined a ListView like this:
<ListView x:Name="libraryBooksListView"
AutomationProperties.AutomationId="VideoListView"
AutomationProperties.Name="Videos"
TabIndex="1"
Padding="0,0,4,0"
ItemsSource="{Binding}"
IsSwipeEnabled="False"
ItemTemplate="{StaticResource LibraryBooksItemTemplate}"
ItemContainerStyle="{StaticResource LibraryListViewItemStyle}"
Grid.Column="1"
SelectionMode="None">
</ListView>
and I defined the LibraryBooksItemTemplate like this:
<DataTemplate x:Key="LibraryBooksItemTemplate">
<Grid Margin="0">
<GridView x:Name="booksGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{StaticResource textbookTemplateSelector}"
SelectionMode="Multiple"
IsItemClickEnabled="True"
ItemClick="booksGridView_ItemClick"
SelectionChanged="booksGridView_SelectionChanged"
IsSwipeEnabled="false"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</DataTemplate>
The GridView, booksGridView, has multiple items (books).
How to modify/access the "ItemTemplateSelector" and SelectionMode etc. of the GridView?
Is there a way to access each of the items in the booksGridView?
Thx
There are many ways to do that.
The easiest one is to wrap your DataTemplate contents into a UserControl.
Another one is to use something like ContainerFromIndex().
Then you can also use VisualTreeHelper class to walk the visual tree.
Then again you can subclass your ItemsControl and override GetContainerForItemOverride() or
PrepareContainerForItemOverride() or
use the ItemContainerGenerator property
The imporant thing to note is that your ItemsSource provides items to the control while the overrides or the generator provide containers to display the items using the ItemTemplates.
*Edit As for your additional questions:
How to modify/access the "ItemTemplateSelector" and SelectionMode etc. of the GridView?
You have defined your selector resource and gave it a key of "textbookTemplateSelector", so you can just get it with this.Resources["textbookTemplateSelector"]. SelectionMode you can bind to the same source DataContext you bound your ItemsSource to and change or read it through a binding.
Is there a way to access each of the items in the booksGridView?
Yes. Since your DataContext is set as the ItemsSource of your ListView - you can access all the items through that DataContext. Each of these items seems to have an Items property that is bound to your GridView, so you can access each of these through the Items property you have defined yourself.
You can access it by using ItemsSource:
foreach(var book in this.booksGridView.ItemsSource)
{
}
I have a Silverlight application with a formular. The formular has a TextBox and a ListBox.
<TextBox Text="{Binding Value, Mode=TwoWay}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>
I focus the TextBox and write something into it. After this I select an item in the ListBox. The ViewModel seems to set "SelectedItem" BEFORE "Value". Why? How can I fix the order? I mean I need to process the TextBox before the ListBox.
Thanks
Unfortunately, that looks like a bug. Same example on WPF will cause the TextBox to be set before the ListBox. You would have to find another way of doing what you want by slightly changing the logic of how you app UI functions.
You can update your TextBox Text property binding on TextChanged event, not LostFocus how it is now. Here is a sample.
The TextboxBinding is by default updating on LostFocus, try changing your binding to this:
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>