Xaml Tag binding fails in button flyout for windows 8.1 store app - windows-store-apps

I have a windows 8.1 store app and I can't figure out how to get the datacontext to access my viewmodel for a relaycommand. The xaml works all the way up to the flyout and then it fails. So the button with content "buttonWorks" successfully gets the binding from the rootGrid element and calls the command on the viewmodel. But the button right below in the flyout does not. Why?
To make an example of the binding problem, create a new Store App with the Split App template. Then add a flyout to the SplitPage and bind a textbox text to the itemtitle element. The binding will not populate the flyout textbox. The code snippet looks like this:
<Image Source="{Binding ImagePath}" Grid.Row="1" Margin="0,0,20,0" Width="180" Height="180" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
<StackPanel x:Name="itemDetailTitlePanel" Grid.Row="1" Grid.Column="1">
<TextBlock x:Name="itemTitle" Margin="0,-10,0,0" Text="{Binding Title}" Style="{StaticResource SubheaderTextBlockStyle}"/>
<TextBlock x:Name="itemSubtitle" Margin="0,0,0,20" Text="{Binding Subtitle}" Style="{StaticResource SubtitleTextBlockStyle}"/>
<Button Content="Update">
<Button.Flyout>
<Flyout>
<StackPanel>
<StackPanel Margin="5" Orientation="Vertical" >
<TextBlock Text="Item Title" VerticalAlignment="Bottom"/>
<TextBox Text="{Binding ElementName=itemTitle,Path=Text,Mode=TwoWay}" Width="200" />
</StackPanel>
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
I can get the command binding to work using Dani's answer and setting the datacontext on the button hosting the flyout like this, but I can't bind the textboxes as seen in the template example above
<Button Content="Update" HorizontalAlignment="Center" DataContext="{Binding ViewModel, ElementName=pageRoot}" >
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock Text="Item Title" VerticalAlignment="Bottom"/>
<TextBox Text="{Binding ElementName=itemTitle,Path=Text,Mode=TwoWay}" Width="200" />
<Button x:Name="buttonTest" Margin="5" Height="40" Content="Test" HorizontalAlignment="Center" Command="{Binding UpdateMatchDataCommand}"/>
Original Code Example Problem:
<Grid Name="rootGrid" Tag="{Binding}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
....
<ScrollViewer
x:Name="itemDetail"
AutomationProperties.AutomationId="ItemDetailScrollViewer"
Grid.Row="0"
Grid.Column="1"
Grid.RowSpan="2"
Padding="60,0,66,0"
HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
DataContext="{Binding SelectedItem, ElementName=itemListView}"
<Grid x:Name="itemDetailGrid" Margin="0,60,0,50">
<StackPanel Orientation="Vertical" Grid.Row="1" Margin="0,0,10,0" Width="180" Height="180">
<Button Name="buttonWorks" Content="Test" Command="{Binding Tag.UpdateMatchDataCommand,ElementName=rootGrid}"/>
<Button Content="Update" HorizontalAlignment="Center" >
<Button.Flyout>
<Flyout>
<Button Name="buttonFail" Content="Test" Command="{Binding Tag.UpdateMatchDataCommand,ElementName=rootGrid}"/>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
....

If you work with ViewModels I would suggest that you change the DataContext to your page.
<Page
x:Name="rootPage"
DataContext="{Binding ViewModel, RelativeSource={RelativeSource Self}}"
...
And CodeBehind:
private readonly ViewModel _viewModel = new ViewModel();
public ViewModel ViewModel
{
get { return _viewModel; }
}
Now you can change your commands to:
<Button Name="buttonWorks" Content="Test" Command="{Binding Tag.UpdateMatchDataCommand}"/>
ElementName is now only necessary if you bind to a property in code behind.

It ends up that I could never solve the problem using the binding that the template provides. It appears to me that changing the datacontext of a single element in the flyout is not allowed. So, the way I got around it is to create a selected item in the viewmodel and changed the template code to bind to the selected item on view model. Then bind all elements including the command to the same datacontext for the entire form.
<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemsListView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.Row="1"
Margin="-10,-10,0,0"
Padding="120,0,0,60"
ItemsSource="{Binding Matches}"
SelectedItem="{Binding SelectedMatch, Mode=TwoWay}"
IsSwipeEnabled="False">
<ListView.ItemTemplate>
<DataTemplate>
Now the binding works for all fields including the template.

Related

How to pass CommandParameter on holed item?

How to pass CommandParameter on holed item?
my xaml code
<ListView Grid.Row="1" Name="ProfilesListView" SelectedItem="{Binding SelectedUser,Mode=TwoWay}" ItemsSource="{Binding Path=ViewAllProfile,Mode=TwoWay}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" HorizontalAlignment="Center">
</ItemsWrapGrid>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<I:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Holding">
<core:InvokeCommandAction Command="{Binding Path=HoldingCommand}" CommandParameter="{Binding ElementName=ProfilesListView,Path=SelectedItem}" ></core:InvokeCommandAction>
</core:EventTriggerBehavior>
</I:Interaction.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10,0,0,0">
<Image Margin="10" Source="{Binding ImageURL}" Width="150" Height="150" >
</Image>
<TextBlock x:Name="userName" Text="{Binding MenuName}" Foreground="White" HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
my viewmodel is .i am not getting the holding item details .how to solve this
_HoldingCommand = new RelayCommand<object>(HoldedUser);
Not sure this can be done directly through MVVM binding.
The holding event won't set the selected item straight away...
If you would register to the holding event and use code behind, you'll notice the 'holded' item is only known in the HoldingRoutedEventArgs - something like this:
private async void OnListViewHolding(object sender, HoldingRoutedEventArgs e)
{
var selectedItemThroughHolding = e.OriginalSource.DataContext as ***Model;
}
So my suggestion would be to use this code behind event and reroute the selectedItem to the viewmodel there...

ListPicker DataBinding

I am using a toolkit:Listpicker for wp8 with data binding.
there is a textbox in the datatemplate of listpicker which is taken from an element of List projectList.
I have done the binding in the code this ways :
List<Project> lists= new List<Project>();
listPickerOptions.ItemSource = lists;
The textbox is binded to the data, but since the data is more than 5, when i select the data it takes me to a new screen where each element is shown as namespace.Project
I am new to databinding.
Following is the .xaml part for listpicker
<StackPanel Orientation="Vertical" Height="167" Margin="0">
<TextBlock Text="Domain" Margin="13,0,285,0" x:Name="Domain"/>
<TextBox IsEnabled="False" Text="Redmond" x:Name="Domain_txtBox" Visibility="Collapsed"/>
<toolkit:ListPicker x:Name="listPickerDomainOption" ItemsSource="{Binding Title, ElementName=this}" HorizontalAlignment="Right" Height="123" Margin="0,0,11,-30" VerticalAlignment="Top" Width="442" ExpansionMode="ExpansionAllowed" Visibility="Collapsed">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Tag="{Binding ID}"/>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
</StackPanel>
What am I missing?
You just forgot to define the Full Mode Template. Since you didn't it will just show the class structure of the ItemsSource. Here the sample code for both templates, make sure you have them both.
<toolkit:ListPicker x:Name="myLP">
<!-- non full mode -->
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<StackPanel>
<!-- YOUR XAML TAGS FOR BINDING -->
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<!-- full mode -->
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<StackPanel>
<!-- YOUR XAML TAGS FOR BINDING -->
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>

How to create dynmaic pivot items for ItemsControl in windows phone?

create Pivot control with dynamic pivot items, within the pivot datatemplate have to show Items control that too will have data template..like below
<phone:Pivot x:Name="chatPivot" Margin="0 2 0 76" ItemsSource="{Binding Contacts}" SelectionChanged="chatPivot_SelectionChanged"> <phone:Pivot.ItemTemplate>
<DataTemplate>
<ScrollViewer x:Name="chatScroll" Margin="0,0,0,72" VerticalScrollBarVisibility="Auto">
<ItemsControl Margin="0" x:Name="chats" Tap="chats_Tap_1" ItemsSource="{Binding Messages}"
ItemTemplate="{StaticResource imgItemTemplate}" ItemsPanel="{StaticResource imgItemPanel}">
</ItemsControl>
</ScrollViewer>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
Here is my dataTemplate.
<phone:PhoneApplicationPage.Resources>
<ItemsPanelTemplate x:Key="imgItemPanel">
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
<DataTemplate x:Key="imgItemTemplate" >
<chatbubble:ChatBubbleControl x:Name="ChatBubble" Hold="ChatBubbleControl_Hold_1" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I actually do not know the design of your "ChatbubbleControl" usercontrol but I found one issue why values are not getting bound.
<phone:PhoneApplicationPage.Resources>
<ItemsPanelTemplate x:Key="imgItemPanel">
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
<DataTemplate x:Key="imgItemTemplate" >
<chatbubble:ChatBubbleControl x:Name="ChatBubble" xyz="{Binding}" Hold="ChatBubbleControl_Hold_1" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
You are binding value to ItemsControl but you are not binding any value to actual control (here, chatbubblecontrol) that is displaying the value on screen.
The solution is the you need to create a property to your usercontrol e.g.: Here, I made a test property named "xyz". and then try to bind the values to it.
Hope this will help you conceptually.

WP8 Progress Bar Not Rendering

I have placed a Progress Bar control within my MainPage.xaml. The application type is Pivot.
For some reason, the Progress Bar and a TextBlock which I have placed within a PivotItem and below a Grid are not showing. There is a LongListSelector directly beneath these two controls. Are these two controls not showing because of that? I used the UI to drag the LongListSelector beneath then anyway, so I'm not sure why it's not showing.
This is the XAML:
<phone:Pivot Title="Title" Background="White" Foreground="Black">
<!--Pivot item one-->
<phone:PivotItem Header="Header" Foreground="Black">
<Grid>
<ProgressBar Name="progressBar" Value="0" IsIndeterminate="True" Margin="0,0,0,579"/>
<TextBlock Name="txtLastUpdated" FontWeight="Black" FontStyle="Italic" Foreground="Black" Margin="0,24,0,541" />
<phone:LongListSelector Name="llsLocations" ItemsSource="{Binding}" SelectionChanged="LongListSelector_OnSelectionChanged" Margin="0,62,0,0">
<phone:LongListSelector.ItemTemplate>
...
...
...
As you can see, there is a ProgressBar and a TextBlock above the LongListSelector who are also inside the Grid control.
Any ideas why these two controls are not showing?
I think you have something wrong with Margin or item positioning. I've tested code below and it works:
<phone:Pivot Title="Title" Background="White" Foreground="Black">
<!--Pivot item one-->
<phone:PivotItem Header="Header" Foreground="Black">
<Grid>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<ProgressBar Name="progressBar" Value="0" IsIndeterminate="True" VerticalAlignment="Center" Margin="0"/>
<TextBlock Name="txtLastUpdated" FontWeight="Black" FontStyle="Italic" Foreground="Black"
HorizontalAlignment="Center" Text="Something"/>
</StackPanel>
<phone:LongListSelector Name="llsLocations" ItemsSource="{Binding}" SelectionChanged="LongListSelector_OnSelectionChanged" Margin="0,62,0,0"/>
</Grid>
</phone:PivotItem>
</phone:Pivot>
Remove margin of all child element of StackPanel. This will defiantly helps you.
<phone:Pivot Title="Title" Background="White" Foreground="Black">
<!--Pivot item one-->
<phone:PivotItem Header="Header" Foreground="Black">
<Grid>
<StackPanel>
<ProgressBar Name="progressBar" Value="0" IsIndeterminate="True"/>
<TextBlock Name="txtLastUpdated" FontWeight="Black" FontStyle="Italic" Foreground="Black" />
<phone:LongListSelector Name="llsLocations" ItemsSource="{Binding}" SelectionChanged="LongListSelector_OnSelectionChanged" >
<phone:LongListSelector.ItemTemplate>
</StackPanel>
</Grid>
</phone:PivotItem>
</<phone:Pivot>
Hardcoding control's position (especially by dragging controls in designer) is not a good practice. Try to define rows for your Grid, then specify Grid.Row for controls inside the Grid. With that you can arrange Grid content more neatly. Check this link for more sample and explanation about layouting controls inside Grid. Following is an example for your situation :
<phone:PivotItem Header="Header" Foreground="Black">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<ProgressBar Name="progressBar" Value="0" IsIndeterminate="True" />
<TextBlock Name="txtLastUpdated" FontWeight="Black" FontStyle="Italic" Foreground="Black" />
</StackPanel>
<phone:LongListSelector Grid.Row="1" Name="llsLocations" ItemsSource="{Binding}" SelectionChanged="LongListSelector_OnSelectionChanged" >
<phone:LongListSelector.ItemTemplate>
...
...

Windows Store Apps ListView DataTemplate

I have a listview in my Windows store app:
<ListView ItemsSource="{Binding}" x:Name="lView" Grid.Column="1" HorizontalAlignment="Left" Height="586" Margin="74.714,105,0,0" VerticalAlignment="Top" Width="741" ItemTemplate="{StaticResource ImageTextListMailFolderTemplate}"/>
and a data template for this listview:
<DataTemplate x:Key="ImageTextListMailFolderTemplate">
<Grid Width="280">
<TextBlock Text="some text" FontSize="24" FontWeight="Light"
Margin="10,10,0,0" HorizontalAlignment="Left"
TextTrimming="WordEllipsis" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
In C# code, I'm using this as a source for listview:
List<string> GridViewData = new List<string>();
lView.ItemsSource = GridViewData;
My problem is: when I use listview without the template, all data from GridViewData is displayed in listview. But when I use DataTemplate, in each listview item is text "some text" like it is defined in template. But I want to use template, and in each item of listview show data from GridViewData. Can somebody help me please, how to do this?
Thank You
The text binding in your DataTemplate should be something like this:
Text="{Binding}"
Here is the full DataTemplate code:
<DataTemplate x:Key="ImageTextListMailFolderTemplate">
<Grid Width="280">
<TextBlock Text="{Binding}" FontSize="24" FontWeight="Light"
Margin="10,10,0,0" HorizontalAlignment="Left"
TextTrimming="WordEllipsis" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>