Select ListView Element on button Click using MVVM - mvvm

I have one list as RoomGroupList and another as RooList,One Room Group have multiple Roos in it, like
RoomGroup 1 => Room-1
Room-2
Room-3
I have bound RoomGroupList to ListView and RoomGroupControll is Generating From it as,
<ListView x:Name="lstRoomGroupList" SelectionMode="Single" ItemsSource="{Binding roomGroupList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding evokoRoomGroup,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<ListView.ItemTemplate>
<DataTemplate>
**<UserConrols:RoomGroupControl/>**
</DataTemplate>
</ListView.ItemTemplate
Now RoomGroupControl has one ListView to Listout No.ofRooms in it as,
<ListView x:Name="lstRoomList" Grid.Row="3" ItemsSource="{Binding GetroomList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding DataContext.EvokoRoom,ElementName=tbDashBoard,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Stretch" VerticalAlignment="Top" Background="#F3F3F5"
BorderBrush="LightGray" BorderThickness="0"
Margin="0,0,0,0" Height="Auto" MaxHeight="200" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
**<UserConrols:RoomControl/>**
</DataTemplate>
</ListView.ItemTemplate>
what I want is,when I click on any button from ListElements at that time it's corresponding ListItem(row) should be selected so that I have added EventSetter using Resource on RoomGroupList as
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
</ListView.Resources>
It's working properly for RoomGroupList I'm able to select Different Groups but Problem is I Can't select Rooms From RoomGroup which I have selected.
If anyone knows how to manage this, can also provide me Links and Suggestions,Thanks.

Related

TapGestureRecognition in Xamarin Forms Listview

I need to check if the empty part of a Xamarin Forms Listview is tapped. For example, there are 5 rows and the space below those filled rows is tapped a method should be called.
I tried adding Tapgesturerecognizer to the Listview and the page containing the listview but this didnt work.
Is there a way to check if someone tapped the empty space in the listview?
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First Item</x:String>
<x:String>Second Item</x:String>
<x:String>Third Item</x:String>
<x:String>Fourth Item</x:String>
<x:String>Fifth Item</x:String>
<x:String>Sixth Item</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}"
d:Text="{Binding .}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding Description}"
d:Text="Item descripton"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped" NumberOfTapsRequired="1"></TapGestureRecognizer>
</ListView.GestureRecognizers>
</ListView>
Try to adding footer to the Listview
<ListView
x:Name="ItemsListView"
...>
<ListView.Footer>
<ContentView>
<ContentView.GestureRecognizers>
<TapGestureRecognizer />
<ContentView.GestureRecognizers>
</ContentView>
</ListView.Footer>
</ListView>
set footer view and place your TapGestureRecognizer
Checkout this https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/interactivity#selection-and-taps.
it discusses the selection activity in the ListView so u can execute some logic When an item is selected
Update:
Remove Code in the Screenshot then configure the ListView item selection as shown in the link.
then put the ListView (make sure that the list view fill only the space it needs) In a StackLayout and Configure the Tapped event of the stackLayout with the logic u need to execute on clicking the empty page.

Binding ObservableList's items properties in DataTemplate's Textblock [duplicate]

This question already has an answer here:
Databinding MediaPlaybackItem to ListView Item in DataTemplate
(1 answer)
Closed 5 years ago.
i want to use some of the MediaPlaybackItem properties(Artist , Title etc.) and bind them in the Listbox data template.Unfortunately MediaPlaybackItem can only access the meta of a song by calling MediaPlaybackItem.GetDisplayProperties().MusicProperties.Title;
In my ListView i have bind as a ItemSource observable list of MediaPlaybackItems :
<ListView x:Name="SongList" HorizontalAlignment="Left" Visibility="Visible" Height="773" Background="{Binding}"
Opacity="0.5" SelectedValue="selectedFile"
ItemsSource="{Binding MediaModels.ListOfMediaPlaybackItems , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}"
Then i have the ListView data template :
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border BorderBrush="#404040" BorderThickness="0,0,0,2" HorizontalAlignment="Stretch"
Width="282" Height="80">
<Grid HorizontalAlignment="Left">
<TextBlock Text="{Binding MusicPropertiesTitle}" TextWrapping="WrapWholeWords"
Margin="82,10,10,0" />
<Grid Margin="0,0,-140,0">
<Image Source="Images/Album.png" Width="70" Height="70" Margin="0,0,350,0" />
</Grid>
</Grid>
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I cannot find a way to bind each MediaPlaybackItem's property(MediaPlaybackItems .GetDisplayProperties().MusicProperties.Title;) to the TextBlock of the DataTemplate .
I hope you understand what i want! Your help is Greatly appreciated!
Best regards
I never use mediaPlaybackItems but would load each property you want into a class and load the class into the observable collection if i understood what you want correctly. If you need help doing that let me know.

TreeView HierarchicalDataTemplate with Navigation Properties EntityFramework

I have three linked Entities (Categories->Types->Classes) with one to many relationship.
Is it possible to bind only Categories entity and represent the rest using Navigation properties andHierarchicalDataTemplate ?
I imagine something like this :
<TreeView ItemsSource="{Binding Categories}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Categories}" >
<TextBlock Foreground="Red" Text="{Binding Types}" />
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Classes}">
<TextBlock Text="{Binding TypeName}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding ClassName}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I've done this recently, in a WPF project, I've updated the Types to match your names and Nav Properties.
You might want to consider changing Type/Class to something more specific since they're used as keywords in the c# language, but I think you get the idea
<!-- The Root Category Table -->
<HierarchicalDataTemplateDataType="{x:Type Entities1:Categories}" ItemsSource="{Binding Types}" >
<StackPanel Orientation="Horizontal">
<Image Name="img" Source="{Binding ., Converter={Converters:DataTypeImageConverter}}" />
<TextBlock Text="{Binding CategoryName}" FontWeight="Bold" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- Your Type Table -->
<HierarchicalDataTemplate DataType="{x:Type Entities1:Type}" ItemsSource="{Binding Classes}" >
<StackPanel Orientation="Horizontal">
<Image Name="img" Source="{Binding ., Converter={Converters:DataTypeImageConverter}}" />
<TextBlock Text="{Binding TypeName}" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- Your Class Table-->
<DataTemplate DataType="{x:Type Entities1:Class}">
<StackPanel Orientation="Horizontal">
<Image Name="img" Source="{Binding ., Converter={Converters:DataTypeImageConverter}}" />
<TextBlock Text="{Binding ClassName}" />
</StackPanel>
</DataTemplate>
What this will do is, it will match the datatype in the tree - If it matches Category, it will create the stackpanel, then start another branch, using the navigation collection Types.
For types, it will do the same basic thing - create the panel for that item, then another branch, for it's navigation collection Class.
If it's class, it will only create the panel, since it's a DataTemplate, not a HierarchicalDataTemplate

How to bind a combobox having an item as a datagrid in wpf? The ComboBox itself is a part of a Datatemplate

I have a TabControl generating some tab items following the MVVM pattern using WPF.
The TabControl ItemTemplate i.e. for each of the tab items that is generated, I have a combobox that should show some data from a different list. This list is not the same as the bound object of the Tab Item itself.
For eg: If a tabitem is bound to a address object the combobox should show data from a state list and show the state present in the address object as the selected item.
The Combo box is having only one item as a datagrid which is bound to the state list
The problem is that all data is being shown in all sections but the combo box simply wouldnt show the data. Surprisingly, the Combobox when taken out of the TabControl DataTemplate works fine....
Below is the code both outside and inside the tabcontrol. Some suggestions please !!!
------This one is outside the Tabcontrol and works perfectly--------------
<ComboBox SelectedValue="{Binding SelectedState}" HorizontalAlignment="Left" VerticalAlignment="Center" IsEditable="True" Margin="50,55,0,61" Height="27" Width="193">
<ComboBoxItem TextSearch.Text="{Binding SelectedState}">
<ContentControl>
<DataGrid SelectedIndex="{Binding StateSelectedIndex}" ItemsSource="{Binding StateData}" AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" cal:Message.Attach="[Event SelectionChanged] = [Action SelectionChanged]">
<DataGrid.Columns>
<DataGridTextColumn Header="StateName" Binding="{Binding StateName}" />
</DataGrid.Columns>
</DataGrid>
</ContentControl>
</ComboBoxItem>
</ComboBox>
----This one is inside the TabControl ---------
<TabControl Margin="3,3,0,0" HorizontalAlignment="Left" Width="752" Height="255" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="1" ItemsSource="{Binding Addresses}" SelectedIndex="{Binding WhichAddressTab}" >
<TabControl.ItemContainerStyle>
...................................
</TabControl.ItemContainerStyle>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl>
..........................
<ComboBox SelectedValue="{Binding SelectedState}" HorizontalAlignment="Left" VerticalAlignment="Center" IsEditable="True" Margin="108,3,0,1" Grid.ColumnSpan="3" Grid.Row="1" Width="147">
<ComboBoxItem TextSearch.Text="{Binding SelectedState}" >
<ContentControl>
<DataGrid SelectedIndex="{Binding StateSelectedIndex}" ItemsSource="{DynamicResource StateData}" AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" cal:Message.Attach="[Event SelectionChanged] = [Action SelectionChanged]">
<DataGrid.Columns>
<DataGridTextColumn Header="StateName" Binding="{Binding StateName}" />
</DataGrid.Columns>
</DataGrid>
</ContentControl>
</ComboBoxItem>
</ComboBox>
...........................
</Grid>
</ContentControl>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
I have tried searching and have understood the problem is with the databinding within a datatemplate, but have been unable to achieve the desired result.
Yes, the problem is with your binding. The DataContext inside of the DataTemplate is for a single element (from the collection bound to the ItemsSource). Meaning that you can't access properties that are directly on the ViewModel itself.
To work around this, you can name the TabControl for example, and convert your bindings inside of the DataTemplate to use ElementName bindings. Another solution, if you have your ViewModel defined as a Static Resource, is to bind directly to the resource, and use the Path to specify the property to which you want to bind.
Hope this helps :)

Treeview SelectedItem is sometimes the VM and sometimes TreeViewItem

I have a TreeView that the user navigates to select an item for display in a grid. Briefly the XAML looks like this:
<local:TreeViewEx x:Name="theTreeView" ItemsSource="{Binding theData}">
<local:TreeViewEx.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding theChildData}">
<TextBlock Text="{Binding Name}"/>
</sdk:HierarchicalDataTemplate>
</local:TreeViewEx.ItemTemplate>
</local:TreeViewEx>
<Grid DataContext="{Binding ElementName=theTreeView, Path=SelectedItem}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding}" />
<TextBlock Text="{Binding Name}" /></StackPanel>
</Grid>
As the user clicks through the treeview the viewmodel type name is displayed along with the value of the Name property. Perfect. Howerver the user can also execute a search of the treeview (following to Josh Smith) which sets the IsSelected property of the TreeViewItem. Once that happens the {Binding} displays TreeViewItemEx rather than the ViewModel type name, and of course the Name property is not displayed.
How is that possible that the selectedItem would sometimes by the ViewModel, and sometimes be the TreeViewItem?
If you replace your grid with a ContentControl you can then use a DataTemplateSelector.
<ContentControl Content="{Binding ElementName=theTreeView, Path=SelectedItem}"
ContentTemplateSelector="{StaticResource TreeViewItemSelector}" />
On the DataTemplateSelector you can then reference two templates for the different types
<DataTemplate x:Key="ModelTemplate">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<TreeViewItemSelector x:Key="TreeViewItemSelector"
ModelTemplate="{StaticResource ModelTemplate}"
TreeItemTemplate="{StaticResource TreeItemTemplate}" />
In the selector you will then want logic like this
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ModelType)
return ModelTemplate;
if (item is TreeViewItem)
return TreeItemTemplate;
throw new NotImplementedException();
}