The problem is that the user interface (the ListBox) is not updated when new items enter its collection. I've a ListBox which is defined as follows:
<ListBox x:Name="ui_UserList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionChanged="ui_UserList_SelectionChanged" ItemsSource="{Binding chatUsers}" Grid.ColumnSpan="3" Margin="10,179,10,81" DataContext="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<TextBlock Text="{Binding nickname}" HorizontalAlignment="Center" TextAlignment="Center" FontSize="42" Grid.Row="0" Grid.Column="0" Foreground="Black" VerticalAlignment="Top" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The itemsource ChatUsers is an ObservableCollection. This was originally designed as an application for Windows Phone 8, where the ListBox equivalent works as expected (it updates when an item enters the collection).
Is there something about the ListBox that I've missed?
Ok, looks like I needed to set the DataContext explicitly even though it never complained about it.
The only change is this:
<ListBox x:Name="ui_UserList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionChanged="ui_UserList_SelectionChanged" ItemsSource="{Binding chatUsers}" Grid.ColumnSpan="3" Margin="10,179,10,81" DataContext="{StaticResource ChatUsersViewModel}">
.....
</ListBox>
Related
I have a strange issue. I have a listview which contains expander. That expander contains button. When I try to click on it - I am getting an error stating "Cannot find source: Element name".
When I remove CommandParameter from the code and place it again during the runtime - it works. Any ideas why that is happening? All TextBlocks are bind correctly and there are no issue, except for those buttons
Listview:
<ListView x:Name="customMeetingsListView"
Grid.Row="2"
ItemsSource="{Binding CustomMeetingsList}"
Style="{StaticResource CtMeetingsListView}"/>
List view item template:
<Style x:Key="CtMeetingsListView" TargetType="{x:Type ListView}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Expander Background="Transparent">
<Expander.Header>
...
</Expander.Header>
...
<materialDesign:Badged Grid.Row="0"
HorizontalAlignment="Right"
Badge="{Binding RelatedFiles.Count}"
Padding="0 0 8 0">
<materialDesign:PopupBox
Background="Transparent"
StaysOpen="True">
<Button Background="{DynamicResource CardBackground}"
Margin="0 -8 0 -10"
BorderThickness="0"
Command="{Binding ElementName=customMeetingsListView, Path=DataContext.AddCaseFileCommand}"
CommandParameter="{Binding}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="FileDocumentEditOutline"
VerticalAlignment="Center"
Foreground="DarkSlateGray"
Width="12" Height="12"/>
<TextBlock Margin="10 0 0 0"
Text="Add new"
Foreground="DarkSlateGray"
VerticalAlignment="Center"
FontSize="10"/>
</StackPanel>
</Button>
</materialDesign:PopupBox>
</materialDesign:Badged>
DataContext is bind via Prism:
<UserControl
...
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
...
</UserControl>
View model:
private DelegateCommand<CustomMeetingEntity> _addCaseFileCommand = null;
public DelegateCommand<CustomMeetingEntity> AddCaseFileCommand => _addCaseFileCommand ?? (_addCaseFileCommand = new DelegateCommand<CustomMeetingEntity>(AddCaseFile));
Regards,
Eddie
<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]}"
I am trying to make a column chart using WPF. For the Y axis I have a list of values which I would like to display on the control.
I have a ListView bound to the collection. How can I get the items to spread over the entire length of the list view rather then squish together at the top? And is the ListViewthe correct control to use for this?
Here is a sample of my Xaml:
<ListView Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"
ItemsSource="{Binding YAxisValues}"
Background="Gray" VerticalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Path=Value}"
Foreground="White"
HorizontalAlignment="Left"
FontSize="12" Width="50"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
On the left is the list view as i currently have it.
On the right is my desired result.
How can I change my ListView to get there? Or do I need to use a different control entirely?
with UniformGrid used as ItemsPanel items get equal height
<ListView Name="Axis" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"
ItemsSource="{Binding YAxisValues}"
Background="Gray" VerticalContentAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<!--no changes-->
</ListView.ItemTemplate>
</ListView>
there can be a issue when ListView doesn't have enough height for all elements. In that case I would put ListView into ViewBox
Set HorizontalContentAlignment to Stretch for items.
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
I'm having issues with scrolling through ListViews in my Windows Phone 8.1 App. Short lists scroll just fine, scrolling smoothly however as soon Virtualization kicks in the entire ListView "wobbles" to the left slightly, but noticeable enough to be annoying.
I've tried remove all the transitions to no effect as well as having items load incrementally to no success. Setting the item panel to a StackPanel (removing virtualization) fixes the issue but is not preferable.
My listviews are binding to a property in the DefaultViewModel that comes with the Basic Page Template.
What am I doing wrong and what are causing my ListViews to exhibit this behavior?
XAML:
<ListView x:Name="searchResultsList" IsItemClickEnabled="True" ItemClick="ListView_ItemClick" ItemsSource="{Binding searchResults}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,0,0,20" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Width="80" Height="80">
<Image Source="{Binding Image}" />
</Border>
<StackPanel Grid.Column="2">
<TextBlock Text="{Binding PodcastTitle}" TextWrapping="WrapWholeWords" FontSize="{StaticResource TextStyleExtraLargeFontSize}" />
<TextBlock Text="{Binding LastUpdated, Converter={StaticResource dateConverter}}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
<TextBlock Text="{Binding PodcastArtist}" TextWrapping="WrapWholeWords" Style="{ThemeResource ListViewItemContentTextBlockStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
So this seems to be an OS issue, as evidenced in this thread on the MS forums: http://social.msdn.microsoft.com/Forums/en-US/9a363d33-5760-4d38-9c81-84259c4edcbe/listview-jiggles-horizontally-when-large-item-about-to-scroll-in-or-out-in-windows-phone-81-preview?forum=WindowsPhonePreviewSDK&prof=required.
The issue does indeed lie in virtualization, with items that have no fixed width. Using star as the width or making the horizontal alignment stretch won't work so the only solution that takes account orientation and resolution was to bind the width to the ListView's container's ActualWidth property:
<Grid x:name="contentRoot" Margin="19,9.5,19,0">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width={Binding ActualWidth, ElementName=contentRoot} />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
The first element in the listview is not displayed because the ActiualWidth of the Grid is 0 in the first second, when loaded the page. This is the solution, that's working for me:
<Grid x:Name="contentRoot" Margin="20">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid MinWidth="{Binding ActualWidth, ElementName=contentRoot}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
This is a really annoying bug. I can't understand why this is not fixed since years now.
Imho stretching items in a vertical scrolling listview is a very basic feature and should work 100%.
A possible workaround is also this snipped, which should also be aware of size changes :
public class StrechItemsListView : ListView
{
public StrechItemsListView()
{
SizeChanged += StrechItemsListView_SizeChanged;
}
private void StrechItemsListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (ItemsPanelRoot != null)
{
ItemsPanelRoot.Width = e.NewSize.Width;
}
}
}
Changing the xaml only to a custom listview type is less work and cleaner then edit every datatemplate etc. Just my 2 cents.
My Practice seems to work. At least in WP8.1.
Just set the ItemsPanelTemplate in the <ListView></ListView> Block explicitly, but not use
Style="{StaticResource ListViewStyle1}" or something else.
Sample Code:
<ListView ItemsSource="{Binding RadioList}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollMode="Auto">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="10,3,10,0">
<TextBlock Text="{Binding RadioName}" FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" Width="{Binding PhoneWidth}"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
The HorizontalContentAlignment and Width of VirtualizingStackPanel settings are used to center the content in the ListView .You can move these settings freely.I don't know why, but it does work.
This was fixed on Windows 10 for Windows 8.1 apps
I'm trying to achieve a ToggleButton control template for listbox items. This is to be used in an application where the user can click on the listbox items to show a certain piece of functionality.
The listbox item template is defined as follows:
<Style x:Key="ExampleListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ToggleButton IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<TextBlock x:Name="ExampleTitle" Grid.Row="0" Foreground="#333333"
FontFamily="pack://application:,,,/Resources/Fonts/#Neuropol Regular"
FontSize="16" Height="26" TextAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" Text="{Binding ExampleDisplayName}"
Margin="5"></TextBlock>
<TextBlock Grid.Row="1" Foreground="#333333" Margin="5,-5,5,3" HorizontalAlignment="Stretch"
TextAlignment="Left" FontFamily="Verdana" VerticalAlignment="Top"
TextWrapping="Wrap" Text="{Binding ExampleDescription}"/>
</StackPanel>
</ToggleButton>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and the listbox is defined as
<ListBox x:Name="_examplesListBox"
SelectionMode="Single"
BorderBrush="Transparent"
Background="Transparent"
ItemsSource="{Binding AllExamples}"
ItemContainerStyle="{StaticResource ExampleListBoxItemStyle}"
SelectedItem="{Binding SelectedExample, Mode=TwoWay}"/>
Here I have two textblocks, one bound to ExampleDisplayName, the other bound to ExampleDescription. The effect I am trying to achieve is to get the second textblock (description) to wrap around, constrained by the available space.
This is what I'm getting now:
What I'd like is for the second line showing example description to wrap based on the size of the listbox. When the application starts the listbox should auto-size to the first line + margin.
Any suggestions?
Removing that horizontal scrollbar should help with text wrapping:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
I'm not quite sure how to auto-size ListBox on startup based on first text line size using only XAML.