UWP - adding items to ListView dynamically cause crash - xaml

I have a listview defined like this:
<ListView
x:Name="phonesListView"
Grid.Row="5"
Background="Black"
IsItemClickEnabled="True"
Foreground="Gray" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="auto" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid
Grid.Row="0">
<Grid.ColumnDefinitions >
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox
Grid.Column="0"
VerticalAlignment="Center"
Background="Black"
Foreground="White">
<ComboBoxItem Content="Home" IsSelected="True"/>
<ComboBoxItem Content="{Binding Type}"/>
<ComboBoxItem Content="Office"/>
<ComboBoxItem Content="Fax"/>
</ComboBox>
<Button
Grid.Column="1"
Height="30"
Width="30"
Foreground="Black"
Margin="0, 5, 0, 5"
HorizontalAlignment="Center" Click="RemovePhone">
<Button.Background>
<ImageBrush Stretch="Fill" ImageSource="Assets/appbar.close.png" />
</Button.Background>
</Button>
</Grid>
<TextBox
Grid.Row="1"
Background="White"
Foreground="Black"
FontSize="20"
InputScope="TelephoneNumber"
Text="{Binding Number}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have an private ObservableCollection<Phone> numbers = new ObservableCollection<Phone>();
In constructor I call phonesListView.ItemSource = numbers;
And on some button click I want to add new item to the listView so I call a method:
private void AddPhone(object sender, RoutedEventArgs e) {
Phone phone = new Phone("", Types.HOME);
numbers.Add(phone);
}
But after button click to add a item the app crashes and App.g.i.cs is called and global::System.Diagnostics.Debugger.Break(); is highlighted
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
I'm really new to Universal Windows App, and I read that this is called when something is wrong with XAML code. Could you help me with that? Thanks.

I tried to use ItemsSource="{x:Bind Mode=TwoWay}"
The only way (but not the best, I think) where I could dynamically update a listview was making a method that handle a button event where I add a new element (calling the addmethod) and updating the ItemsSource property of the list view.
private void AnadeDoctorAppBarButton_Click(object sender, RoutedEventArgs e)
{
Doctor A = new Doctor("Mapache", "dentista", "La calle", "La vida", "Lo que sea", "Direccion", "olos");
ViewModel.AnadeDoctor = A;
ListaDePrueba.ItemsSource = ViewModel.ColeccionDoctores;
}
It Works, but I think that is not true Databinding.

Related

Only capture tap event from button contained in ListViewItem without triggering item click - UWP Windows 10

In my UWP app which uses MVVMLight, I have a button contained in my ListViewItem and when clicked I want to display a flyout and provide additional actions for the specific ListViewItem but whenever I tap on the button, I get an error i.e.
System.InvalidCastException: Unable to cast object of
type 'Windows.UI.Xaml.Input.TappedRoutedEventArgs' to
type 'MyApp.ViewModels.ItemViewModel'.
at GalaSoft.MvvmLight.Command.RelayCommand`1.Execute(Object parameter)
at Microsoft.Xaml.Interactions.Core.InvokeCommandAction.Execute(Object
sender, Object parameter) at
Microsoft.Xaml.Interactivity.Interaction.ExecuteActions(Object sender,
ActionCollection actions, Object parameter)
at Microsoft.Xaml.Interactions.Core.EventTr
I understand to some extend why it's happening but how I can I fix this? The button contained in my ListViewItem data template is obviously being passed to the parent which is the listview and the DataTrigger that's defined in the Listview is capturing it.
All I want to do is display a flyout when this button is clicked to provide additional options.
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="{StaticResource SystemControlBackgroundAccentBrush5}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0"
Grid.Column="0"
Grid.RowSpan="4"
Width="90"
Height="90"
VerticalAlignment="Center"
Margin="5,5,0,5">
<Image Width="90"
Height="90"
Source="{Binding Logo}" />
</Border>
<Grid Grid.Row="0" Grid.Column="1" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"
Grid.Row="1" VerticalAlignment="Bottom">
<TextBlock Text="Id:" FontWeight="SemiBold" Foreground="White" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Subject}" Margin="10,0,0,0" Foreground="White" VerticalAlignment="Center"/>
</StackPanel>
<Button Width="30" Height="30"
Command="{Binding AdditionalInfoCommand}"
Grid.RowSpan="4"
Grid.Column="1"
Margin="0,0,12,0">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Stroke="{ThemeResource SystemControlBackgroundAccentBrush}"
Fill="{ThemeResource SystemControlBackgroundAccentBrush}"
StrokeThickness="2">
</Ellipse>
<Image Source="ms-appx:///Assets/Information.png" Width="30" Height="30" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
and my ListView has the following code:
<ListView ItemsSource="{Binding MyList}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
SelectionMode="Single">
<ListView.ItemTemplate>
.... as defined above
</ListView.ItemTemplate>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ItemClickCommand}"
CommandParameter="{Binding SelectedItem}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListView>
Any ideas on how I can resolve this?
UPDATE 1:
I'll re-phrase my question slightly. I've managed to bind the button displayed on the ListViewItem to a specific click event by introducing a RelayCommand (AdditionalInfoCommand) in the item's ViewModel. So now my main problem is the actual error mentioned above which is triggered after AdditionalInfoCommand and I assume it's because it is being captured by the ItemClickCommand. Strange as you would assume that it is using the same ViewModel.
Is there a way to no trigger the itemclick when this button is tapped?
Thanks.
Thierry
I figured it out.
When I tap the button inside my ListView DataTemplate, the button is being passed the Item's ViewModel which is correct but then the tap event is bubbled up back to the parent which is captured by:
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ItemClickCommand}"
CommandParameter="{Binding SelectedItem}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
While there may be a solution to stop the event bubbling, to circumvent the problem, I changed my ItemClickCommand.
It was defined as follows:
private RelayCommand<MyItemViewModel> _itemClickCommand;
public RelayCommand<MyItemViewModel> ItemClickCommand
{
get { return this._itemClickCommand ?? (this._itemClickCommand =
new RelayCommand<MyItemViewModel>((viewModel) =>
ItemClickCommandAction(viewModel))); }
}
I simply changed it to:
private RelayCommand<object> _itemClickCommand;
public RelayCommand<object> ItemClickCommand
{
get { return this._itemClickCommand ?? (this._itemClickCommand =
new RelayCommand<object>((viewModel) =>
ItemClickCommandAction(viewModel))); }
}
I then changed the ItemClickCommandAction to take in an object instead of MyItemViewModel and now, within the method, I check the type of the ViewModel being passed:
private void ItemClickCommandAction(object currentObject)
{
if (currentObject is MyItemViewModel)
{
//go to next page
}
}

Selected Item Pivot for Windows Phone 8.1

I have a problem selecting an item from a Pivot in Windows Phone 8.1. I have a CommandBar that makes navigation between pages belonging to Pivot, and have programmed change in the onClick SelectedItem of each button and the display changes to each page. When I start the application all the buttons, making debug SelectedItem change is made and no exception but the display does not change page. The strangest thing is that when I navigate manually between pages with navigation Pivot and then pressed a button on the CommandBar pages work. The problem only happens when I start the application.
It can happen ?, As I can solve ?, I'm a little frustrated xD.
Here is the code of Pivot and Command Bar:
<Pivot x:Name="pivotMain" Style="{StaticResource PivotStyleMain}" Margin="0,0,-0.333,0" >
<PivotItem x:Name="pvtMenu" Header="Online" DataContext="{Binding Groups}">
<ListView
AutomationProperties.AutomationId="ItemListViewSection3"
AutomationProperties.Name="Items In Group"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding lstMenu}"
ItemTemplate="{StaticResource StandardTripleLineItemTemplate}"
ItemClick="ItemView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
</ListView>
</PivotItem>
<PivotItem x:Name="pvtMenuOffline" Header="Offline" DataContext="{Binding Groups}">
<ListView
AutomationProperties.AutomationId="itmListViewMenuOffline"
AutomationProperties.Name="Items In Group"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding lstMenuOffline}"
ItemTemplate="{StaticResource StandardTripleLineItemTemplatePathImage}"
ContinuumNavigationTransitionInfo.ExitElementContainer="True" ItemClick="ListView_ItemClick">
</ListView>
</PivotItem>
<PivotItem x:Name="pvtInfo" Header="InformaciĆ³n">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView>
<TextBlock Height="Auto" Width="Auto" FontSize="25" Foreground="#7D7D7D">EncuƩntranos en</TextBlock>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0" Grid.Column="0" HorizontalAlignment="Left">
<Image Source="Assets/fb.png" Stretch="UniformToFill" AutomationProperties.Name="imgFcbk" Height="Auto" Width="300" Tapped="Image_Tapped"/>
</Border>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0" Grid.Column="0" HorizontalAlignment="Left">
<Image Source="Assets/tw.png" Stretch="UniformToFill" AutomationProperties.Name="imgFcbk" Height="Auto" Width="300" Tapped="Image_Tapped_1"/>
</Border>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0" Grid.Column="0" HorizontalAlignment="Left">
<Image Source="Assets/yt.png" Stretch="UniformToFill" AutomationProperties.Name="imgFcbk" Height="Auto" Width="300" Tapped="Image_Tapped_2"/>
</Border>
</ListView>
<Border Background="Transparent" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Padding="10">
<Image Source="Assets/componetes dispositivos moviles-22.png" Stretch="UniformToFill" AutomationProperties.Name="imgFcbk" Height="Auto"/>
</Border>
</Grid>
</PivotItem>
</Pivot>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.PrimaryCommands>
<AppBarButton x:Name="barBtnHome" Label="Online" Command="{Binding SomeCommand}" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" Click="barBtnHome_Click">
<AppBarButton.Icon>
<BitmapIcon UriSource="Assets/earth53.png"/>
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton x:Name="barBtnOffline" Label="Offline" Command="{Binding SomeCommand}" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" Click="barBtnOffline_Click">
<AppBarButton.Icon>
<BitmapIcon UriSource="Assets/earth85.png"/>
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton x:Name="barBtnAbout" Label="Info" Command="{Binding SomeCommand}" IsHoldingEnabled="False" IsDoubleTapEnabled="False" IsRightTapEnabled="False" Click="barBtnAbout_Click">
<AppBarButton.Icon>
<BitmapIcon UriSource="Assets/appbar.information.circle.png"/>
</AppBarButton.Icon>
</AppBarButton>
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
And here is the code behind the onclick:
private void barBtnHome_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedItem = this.pvtMenu;
}
private void barBtnAbout_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedItem = this.pvtInfo;
}
private void barBtnOffline_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedItem = this.pvtMenuOffline;
}
Much appreciate your help.
User SelectedIndex instead of SelectedItem.
private void barBtnHome_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedIndex = 0;
}
private void barBtnAbout_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedIndex = 1;
}
private void barBtnOffline_Click(object sender, RoutedEventArgs e)
{
this.pivotMain.SelectedIndex = 2;
}

window phone - How to disable current select item?

I have a xaml :
<phone:LongListSelector Name="llsSourceNews" ItemsSource="{Binding SourceNews}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid x:Name="gridNews">
<Grid.RowDefinitions>
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.Column="0" Source="{Binding icon}" Stretch="Fill" Height="35" Width="70"></Image>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Name}" Foreground="White" TextWrapping="Wrap" FontSize="24" VerticalAlignment="Center"></TextBlock>
<Image Grid.Row="0" Grid.Column="2" Source="/Images/Add-New.png" x:Name="imgAdd" Tap="imgAdd_Tap"></Image>
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
and tap event :
private void imgAdd_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
if(true)
{
this.Visibility = Visibility.Collapsed;
}
}
My problem is : when user tap image,all image is disable.I want to image is disable which is selected.
this in your case refers to the page. If you want to retrieve the image, you have to cast the sender parameter:
private void imgAdd_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
if(true)
{
var element = (FrameworkElement)sender;
element.Visibility = Visibility.Collapsed;
}
}

XAML element inside of ItemsControl DataTemplate sometimes has null parent (WinRT)

I'm making a win8 app. I have an ItemsControl with a DataTemplate. Inside this DataTemplate, there is a Grid. Inside this Grid there is a WebView and a ProgressRing. I have an event for LoadCompleted on the WebView, at which time I want to disable the ProgressRing. My thought was to use the following:
ProgressRing pr = ((sender as FrameworkElement).Parent as Grid).Children.First(t => t.GetType().Equals(typeof(ProgressRing))) as ProgressRing;
pr.IsActive = false;
And this works sometimes, but sometimes it claims that ((sender as FrameworkElement).Parent) is null. I verified from debugging that in these cases, the sender is still the correct WebView. The WebView is being shown on the screen and is formatted correctly - so how could its parent be null?
Here's the XAML:
<ItemsControl Margin="40,0,40,0" x:Name="resultsItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="50,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="100" MaxWidth="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="viewInBrowser" IsEnabled="False" Style="{StaticResource PreviewLinkAppBarButtonStyle}" Margin="0,0,40,0" Click="viewInBrowser_Click_1"></Button>
<TextBlock HorizontalAlignment="Left" TextAlignment="Left" Grid.Column="1" FontSize="30" Margin="0,20,0,20" FontWeight="Bold" FontFamily="Georgia" VerticalAlignment="Center" Text="{Binding Name}"></TextBlock>
<ProgressRing x:Name="loadingProgressRing" Margin="20,0" Grid.Column="2" Foreground="White" IsActive="True" HorizontalAlignment="Left" VerticalAlignment="Center"></ProgressRing>
<WebView ScriptNotify="WebView_ScriptNotify_1" Grid.Column="0" Grid.ColumnSpan="14" Grid.Row="1" Source="{Binding CurrentSearchUrl}" Width="0" LoadCompleted="WebView_LoadCompleted_1"></WebView>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I wouldn't use a WebView in an ItemsControl at all, but you could try putting your entire template in a UserControlm then you handle the event inside of the UserControl and don't need to care about sender, since you can just name the Grid and access a named Grid.

Another "The name 'itembutton' does not exist in the current context" (WP8, XAML)

I know that this question has been posted about a thousand times, but I did not find a solution that solved my problem.
I've got a LongListSelector with this ItemTemplate:
<DataTemplate x:Key="AddrBookItemTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock FontWeight="Bold" Text="{Binding Name}" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="0" Grid.Row="0" />
<Button x:Name="itembutton" CommandParameter="{Binding ItemID}" Content="{Binding ButtonCaption}" Width="150" HorizontalAlignment="Right" Grid.Column="1" Grid.Row="0" Click="ItemButtonClick"/>
</Grid>
</DataTemplate>
So what happens is simply that I get this beautiful error message that I posted in the title. And I do not have a clue, why?!
private void ItemButtonClick(object sender, RoutedEventArgs e)
{
if (sender == this.itemButton) {
....
From the DataTemplate it looks like you're showing this button in a container like a ListBox or LongListSelector.
That means that there isn't an itembutton in this scope (presumably this is either UserControl or PhoneApplicationPage): there is in fact one for each of your ListBoxItems!
You'll have to find another way of finding your button.
Update:
You should find that the DataContext of your button matches the item of the list it is contained in. That's probably the easiest way of proceeding: however if all else fails you can use the Tag property as you suggest.
Like:
private void ItemButtonClick(object sender, RoutedEventArgs e)
{
var theButton = (Button) sender;
var myItem = (TypeOfAnObjectInMyList) theButton.DataContext;
doSomethingWithMyItem(myItem);