<ListView x:Name="listview" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.ZoomMode="Enabled"
ItemsSource="{Binding YourCollection}" DoubleTapped="listview_DoubleTapped" Tapped="listview_Tapped" SelectionChanged="listview_SelectionChanged"
GotFocus ="StackPanel_GotFocus" IsItemClickEnabled="True" ItemClick="ListView_ItemClick"
Margin="162,539,-103,11" Style="{StaticResource ListViewStyle1}" ScrollViewer.VerticalScrollBarVisibility="Disabled" Grid.RowSpan="2">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Height="130" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate >
<DataTemplate>
<StackPanel Orientation="Vertical" Height="130" Width="192" >
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Height="108" Width="192" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding Name}" TextAlignment="Center" Height="22" Width="192" Foreground="White" FontFamily="Assets/GothamLight.ttf#GothamLight"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Need to set the focus or selection to first item of the listview items. The listview contains an array of items, where the focus needs to be targeting first item during start and then retain the last chosen item.
There are multiple options here depending on your coding style. It looks like you're using code behind from our event handlers and binding to a view model class with YourCollection property, so I'll give you both examples. :)
Using code-behind
Update your XAML file to handle the Loaded event and name your ListView:
<Page Loaded="Page_Loaded">
...
<ListView Name="MyListView" ItemsSource="{Binding YourCollection}">
...
</ListView>
Then add the following code your Page_Loaded handler:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
if (MyListView.Items.Count > 0)
MyListView.SelectedIndex = 0;
}
Using view model
Provide a SelectedItem property in your view model (wherever you are defining YourCollection):
private YourItem_selectedItem = null;
public Dumb SelectedItem
{
get { return _selectedItem; }
set { SetProperty<YourItem>(ref _selectedItem, value); }
}
Then bind your ListView to the selected item, as you did with your ItemsSource:
<ListView Name="MyListView" ItemsSource="{Binding YourCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
Finally, just set your SelectedItem after you've loaded your collection items.
This method also has the benefit of replacing your SelectionChanged and ItemClick events. You won't need them because the control changes SelectedItem by default in those situations.
I found a further solution that does not require the Page_Loaded handler nor the property SelectedItem in the ViewModel.
<ListView Name="yourCollectionListView"
ItemsSource="{Binding YourCollection}"
SelectedItem="{Binding RelativeSource={RelativeSource Self}, Path=ItemSource[0]}"/>
Of course you should ensure the list has at least one item. With VisualState.StateTriggers you can hide the ListView if it is empty.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState.StateTriggers>
<StateTrigger IsActive="{Binding YourCollection.Count, Converter={StaticResource EqualToParam}, ConverterParameter={StaticResource Zero}}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="yourCollectionListView.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Define the zero value in the page's resources:
<x:Int32 x:Key="Zero">0</x:Int32>
EDIT
It is even possible to achieve this by binding the following to the SelectedItem property:
SelectedItem="{Binding Path=[0]}"
Related
In my WPF application I have ListBox which contains a collection of items. One item can be added when a button is clicked and it is selected in the opened dialogue. As soon as a item is selected the dialogue closes and the item's image and name should be displayed in my ListBox. Unfortunately the Listbox does not update and nothing changes.
Usercontrol with Listbox:
<ListBox ItemsSource="{Binding BlButtonCollection, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Stretch" SelectedItem="{Binding SelectedSticker}"
HorizontalContentAlignment="Stretch" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
<ListBox.Resources>
<viewmodels1:BindingProxy x:Key="ProxyElement" Data="{Binding}" />
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" Rows="10"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Grid x:Name="f">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnSelectArticle" Background="Transparent" Grid.RowSpan="2" BorderThickness="0"
Command="{Binding DataContext.ButtonClicked,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}}"/>
<Image Height="1.5cm" HorizontalAlignment="Center" Source="{Binding ItemImage.ImageUrl, Converter={StaticResource ImageFormatConverter}}"/>
<TextBlock Text="{Binding ItemName}" Width="4cm" Height="0.8cm" TextWrapping="Wrap" Grid.Row="1" HorizontalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Controls with ListBoxes in main window:
<formats:OneXTwo x:Name="oneXTwo" BlButtonCollection="{Binding BlButtons_2}" IsBlVisible="Visible" Visibility="{Binding Are2StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:ThreeXEight x:Name="threeXEight" BlButtonCollection="{Binding BlButtons_24}" IsBlVisible="Visible" Visibility="{Binding Are24StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:FourXTen x:Name="fourXTen" BlButtonCollection="{Binding BlButtons_40, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" IsBlVisible="Visible" Visibility="{Binding Are40StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}" SelectedSticker="{Binding SelectedBlSticker, Mode=TwoWay}" />
I should mention that I have three different formats and each format is a own user-control. Therfore, they are displayed in a shell-view and based on a ComboBox selection one format is displayed. If I am running the application, select a image nothing happens, but if I change the bound value of the textblock in the list view and switch it back to 'Itemname' the Image and Name are displayed.
Have you set the DataContext to a specific ViewModel?
ObservableCollection can only ensure the add/remove operation for items that can be updated to the UI. If you want to the item property to notify the UI, you should override the setter of the property and implement INotifyPropertyChanged.
I am bit new to WPF (XAML) and I have an ItemsControl bound to a list with a MyCollections property . Now my requirement is initially to show only 1st element from the list and having a Show More button option at the end of list. A click on it would show the rest of the items from the collection.
This is my XAML so far, displaying the whole collection:
<ItemsControl x:Name="ContentRoot" ItemsSource="{Binding MyCollections}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<grid>
<TextBox Text="{Binding }" />
<TextBox Text="{Binding }" />
</grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can have both a ContentControl (which displays the first item of the collection) and an ItemsControl (which displays the whole collection) displayed only when a ToggleButton is checked for example.
<StackPanel>
<StackPanel.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<DataTemplate DataType="{x:Type local:MyViewModel}">
<Grid>
<TextBox Text="{Binding}" />
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentControl Content="{Binding MyCollection[0]}"/>
<ToggleButton x:Name="toggle" Content="Show more"/>
<ItemsControl ItemsSource="{Binding MyCollection}" Visibility="{Binding ElementName=toggle, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
You can then adapt this to fit your exact needs.
I have to do a Master/Detail in UWP
1- If you're in Laptop:
The responsible GridView of show the data of this person appear.
So when you select a item is binded to ViewModel.
<ScrollViewer x:Name="ScrollLista" Grid.Column="0" Grid.Row="1">
<ListView x:Name="Lista" ItemsSource="{Binding Lista}" ItemClick="Lista_ItemClick" SelectedItem="{Binding PersonaSeleccionada, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding nombre}" />
<TextBlock Text="{Binding apellido}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
<Grid x:Name="CRUD" Grid.Column="1" Grid.Row="1" DataContext="{Binding PersonaSeleccionada}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
...
</Grid>
2- When is a mobile:
Only will appear the list and when I select a item this should be two things.
Call to ViewModel by binding using SelectedItem.
Call to code behind using ItemClick, this will be in charge of calling another page.
The problem: ItemClick not working, not call to Lista_ItemClick... How can I call a method and send the item selected to code behind?
For click event to work, IsItemClickEnabled="True" should be added to the ListView.
I have a TabControl bound to an ObservableCollection property of view models, TabViewModelsCollection.
When another property gets set from within the view models, DeviceState, I'd like to raise a property changed event and tell my TabControls ItemSource to refresh.
The problem is my ItemSource is an ObservableCollection of ViewModels and when I call RaisePropertyChanged("TabViewModelsCollection"); nothing gets updated.
Furthermore my tab views contain multiple user controls and bindings.
The scenario that is supposed to play out is: A device is located on the network, data is collected, and the tabs of device information should then be updated.
Currently my TabControl only updates when I select a different device then select the device whos information I want to see. Think left panel list of devices, right panel with tabs of device info.
Let me know what part of the code you guys might want to see, my codebase is quite large so it would be hard to post it.
Here is where the TabControl is defined in my view:
<!-- Devist List Controls -->
<Grid DockPanel.Dock="Left" Margin="5,5">
<local:DeviceListView DataContext="{Binding DeviceListViewModel}" Grid.Row="0"/>
</Grid>
<GroupBox Header="Device Information" DockPanel.Dock="Right" Margin="0,0,5,5">
<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection}" SelectedItem="{Binding DeviceListViewModel.SelectedDevice.SelectedTabItemVm}" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type vms:HomeViewModel}">
<local:HomeTab/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ConfigurationViewModel}">
<Grid>
<local:ConfigurationFileView Visibility="{Binding Configuration, TargetNullValue=Collapsed, FallbackValue=Visible}"/>
<local:ErrorTab Visibility="{Binding Path= Configuration, TargetNullValue=Visible, FallbackValue=Hidden}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ExpansionModulesViewModelFactory}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<DockPanel >
<local:ExpansionModulesList Title="Discovered/Enumerated"
DataContext="{Binding DiscoveredModules}"
/>
<GridSplitter Width="5"/>
<local:ExpansionModulesList Title="User Action Required"
DataContext="{Binding FaultyModules}"
/>
</DockPanel>
</StackPanel>
<DockPanel Grid.Row="1">
<StackPanel Orientation="Horizontal" FlowDirection="RightToLeft" Margin="5" IsEnabled="{Binding IsCommandEnabled}">
<Button Content="Cancel" HorizontalAlignment="Right"
Command="{Binding CancelExpansionCommand }"
ToolTip="Revert all local modifications by refreshing data from the controller." />
<Separator Width="10"/>
<Button Content="Apply" HorizontalAlignment="Center"
Command="{Binding ApplyExpansionCommand }"
ToolTip="Apply all changes to the controller." />
<Separator/>
</StackPanel>
</DockPanel>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:LogViewModel}">
<local:LogView />
</DataTemplate>
<DataTemplate DataType="{x:Type vms:SignalStrengthViewModel}">
<local:SignalStrengthView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
<Setter Property="Header" Value="{Binding Name}" />
</Style>
</TabControl.ItemContainerStyle>
EDIT: I want to be able to call raised property changed on this and have it refresh all of my tab views..
<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection}" SelectedItem="{Binding DeviceListViewModel.SelectedDevice.SelectedTabItemVm}" >
RaisePropertyChanged("TabViewModelsCollection");
Hi please try the next solution:
VM code redaction
private State _deviceState;
private ObservableCollection<object> _tabViewModelsCollection;
public State DeviceState
{
get { return _deviceState; }
set
{
_deviceState = value;
RaisePropertyChanged("DeviceState");
UpdateTabViewModelsCollection();
}
}
public ObservableCollection<object> TabViewModelsCollection
{
get
{
return _tabViewModelsCollection ??
(_tabViewModelsCollection = new ObservableCollection<object>(GetDeviceData()));
}
}
private void UpdateTabViewModelsCollection()
{
_tabViewModelsCollection = null;
RaisePropertyChanged("TabViewModelsCollection");
}
private List<object> GetDeviceData()
{
//implement here the data collection process
throw new NotImplementedException();
}
Xaml redaction (define the UpdateSourceTrigger)
ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection, UpdateSourceTrigger=PropertyChanged}"
Let me know if it was helpful.
Regards.
I'm sorry if the title is a bit, off. Did not know what to call it really.
But here is my question:
I have a ListView with a custom ItemsTemplate, which has a Textblock and an Image. Both of which are set to get their data from binds.
But here is what I'm wondering:
If I want to add listviewItems from XAML:
<ListView HorizontalAlignment="Left" Width="150" ItemTemplate="{DynamicResource menuItems}" ItemsPanel="{DynamicResource menuLayout}">
<ListViewItem/> <---- Here
<ListViewItem/> <---- And here.
</ListView>
How can I set what values the textblock and image should have?
<ListViewItem "TextBlockValue = asdasdasds"/> etc
Here's the Itemtemplate
<DataTemplate x:Key="menuItems">
<Grid Width="150" Height="35">
<Image Height="35" Width="35" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding Path=Text}" Margin="40,0,0,0" VerticalAlignment="Center" FontSize="15" FontWeight="Light" Foreground="White"/>
</Grid>
</DataTemplate>
Simple and most flexible solution
As a first step, a class should be defined which serves as data container for all values of one ListViewItem.
public class ItemData
{
public ImageSource ImageSource { get; set; }
public string Text { get; set; }
}
(Technically, one could also do it also without such a custom class; however, the resulting XAML will look much more convoluted and much less readable.)
The data template with the bindings to the properties of ItemData elements could look like this:
<DataTemplate x:Key="menuItems">
<StackPanel Width="150" Height="35" Orientation="Horizontal">
<Image Source="{Binding Path=ImageSource}" Height="35" Width="35" />
<TextBlock Text="{Binding Path=Text}" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="15" FontWeight="Light" Foreground="White"/>
</StackPanel>
</DataTemplate>
In the XAML of the ListView, a collection of ItemData objects will be constructed and assigned to the ListView.Items property. The ListView will create the ListViewItems accordingly.
<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}" ItemTemplate="{StaticResource menuItems}">
<ListView.Items>
<My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
<My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
</ListView.Items>
</ListView>
Solution with explicit ListViewItem declarations
The question sounds like a solution with explicit declarations of ListViewItems is sought.
However, this should not really be the recommended approach, as it will only lead to more convoluted XAML for achieving exactly the same result as the first solution, as demonstrated now.
In the XAML of the ListView, each ListViewItem together with the appropriate ItemData object will be constructed, and also the data template will be assigned to ListViewItem.ContentTemplate (ListView.ItemTemplate won't work here, since the ListViewItems are not created by the ListView).
<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}">
<ListViewItem ContentTemplate="{StaticResource menuItems}">
<ListViewItem.Content>
<My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
</ListViewItem.Content>
</ListViewItem>
<ListViewItem ContentTemplate="{StaticResource menuItems}">
<ListViewItem.Content>
<My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
</ListViewItem.Content>
</ListViewItem>
</ListView>
If specifying the ContentTemplate for each single ListViewItem is not desired, a ListViewItem Style setting the ListViewItem.ContentTemplate property can be defined in the ListView's resource dictionary:
<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContentTemplate" Value="{StaticResource menuItems}" />
</Style>
</ListView.Resources>
<ListViewItem>
<ListViewItem.Content>
<My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
</ListViewItem.Content>
</ListViewItem>
<ListViewItem>
<ListViewItem.Content>
<My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
</ListViewItem.Content>
</ListViewItem>
</ListView>
The style being defined inside the ListView's resource dictionary prevents any other ListViewItem control outside of this ListView from accidentally picking up this style.
Comparing the simplicity of the first solution with the verbosity of the second, it is obvious that explicit declarations of ListViewItems in XAML is not a recommended approach.