I develop an Universal App, that uses MVVM Light and Navegar. In this app, the main page contains a Pivot, where each PivotItem is bounded to a ViewModel.
This page looks like this:
The XAML looks like this:
<Page
...>
<Page.DataContext>
<Binding Path="MainViewModelInstance" Source="{StaticResource Locator}"/>
</Page.DataContext>
<Page.Resources>
...
</Page.Resources>
<Grid>
<!-- HOME -->
<Pivot x:Uid="homePivot"
x:Name="homePivot"
CommonNavigationTransitionInfo.IsStaggerElement="True"
TitleTemplate="{StaticResource AppPivotTitle}"
Style="{StaticResource CustomizedPivot}">
<Pivot.Background>
<ImageBrush Stretch="Fill"/>
</Pivot.Background>
<PivotItem x:Uid="homePivotitemHome"
Margin="19,14.5,19,0"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Header="Home">
<PivotItem.Background>
<ImageBrush ImageSource="{Binding Infos.background_image, Converter={StaticResource InfosUIImageFondToStringConverter}}"
Stretch="UniformToFill"
Opacity="0.75"/>
</PivotItem.Background>
</PivotItem.ContentTemplate>
</PivotItem>
<!-- NEWS -->
<PivotItem x:Uid="homePivotitemNews"
Margin="19,14.5,0,0"
CommonNavigationTransitionInfo.IsStaggerElement="True" >
<PivotItem.DataContext>
<Binding Path="NewsViewModel" Source="{StaticResource Locator}"/>
</PivotItem.DataContext>
<PivotItem.ContentTemplate>
<DataTemplate>
<Grid>
<ListView ItemsSource="{Binding News}"
IsItemClickEnabled="True"
SelectionMode="Single"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
...
</ListView>
</Grid>
</DataTemplate>
</PivotItem.ContentTemplate>
</PivotItem>
<!-- CONTACTS -->
<PivotItem x:Uid="homePivotitemContacts"
Margin="19,14.5,0,0"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Header="Contacts">
<PivotItem.DataContext>
<Binding Path="ContactsViewModel" Source="{StaticResource Locator}"/>
</PivotItem.DataContext>
<PivotItem.ContentTemplate>
<DataTemplate>
<Grid>
<ListView ItemsSource="{Binding Contacts}"
IsItemClickEnabled="True"
SelectionMode="Single"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
...
</ListView>
</Grid>
</DataTemplate>
</PivotItem.ContentTemplate>
</PivotItem>
...
</Pivot>
</Grid>
</Page>
So the page is bounded to a DataContext "MainViewModelInstance", that is used for the first PivotItem. The others PivotItems have their own DataContext: "NewsViemodel", "ContactsViewModel", ...
On each ViewModel, a constrctor calls a Load() method that updates the datas of this HomePage.
I would like to display a StatusBarProgressIndicator when one of the ViewModels is loading datas, and stopping it when all datas has been loaded.
Currently I show the StatusBarProgressIndicatorby calling a "ShowStatusBarProgress()" method in the "MainViewModel":
private async void LoadData()
{
ShowStatusbarProgress();
// Load data
...
HideStatusbarProgress();
}
private async void ShowStatusbarProgress()
{
progressbar.Text = "Please Wait...";
await progressbar.ShowAsync();
}
private async void HideStatusbarProgress()
{
await progressbar.HideAsync();
}
But I don't see how to do for taking into account all the "Load()" methods of the ViewModels. I heard about Messenger services, but I don't see how it can work in my case.
Related
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...
I've been reading this article about Navigation Drawer and i Succeed, but how can i create a Click Event to each item i have inside of mu ListView?
i have that Array and bind all this to listview!
string[] menuItems = new string[5] { "Item1", "Item2", "Item3", "Item4", "Item5" };
ListMenuItems.ItemsSource = menuItems.ToList();
XAML.....
<Grid x:Name="ListFragment" Background="#F4F4F4">
<ListView x:Name="ListMenuItems" SelectedItem="true" SelectionChanged="ListMenuItems_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="18" Foreground="Black" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Thanks!
Define an event handler for ItemClick event of ListView. You also need to set IsItemClickEnabled property to true.
<ListView x:Name="listview"
IsItemClickEnabled="True"
ItemClick="listView_ItemClick">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
..
..
private void listView_ItemClick(object sender, ItemClickEventArgs e) {
// Code here
}
I have an app where I save the user's contacts in a local Database, then bind this contacts in a LongListSelector using ObservableCollection to update the UI (when a new item is add or deleted).
But I'm having a strange behavior when the ObservableCollection is changed...
The item is add to the UI correctly, but after this, when I scroll fast, a blank space appears in the middle of the list.
Then I found out that, apparently, the list is cutting some items...
I was testing with a list of 140 items (strings), having at least one item starting with each alphabetic letter.
When this problem happens, I saw that after items with C letter, started the items with P letters (D to O disappeared!).
Does anybody can tell me what is happening?
I bind the items on LongListSelector this way:
XAML:
<Grid x:Name="ContentPanelContatos" Grid.Row="1" Margin="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid x:Name="gridContatos" Grid.Row="1" Margin="12,2,12,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,12" >
<TextBox x:Name="tbxSearch" VerticalAlignment="Top" HorizontalAlignment="Stretch" Visibility="Collapsed" TextChanged="TbxSearch_TextChanged" LostFocus="TbxSearch_LostFocus" Style="{StaticResource TextBoxStyle}" />
</Grid>
<phone:LongListSelector Grid.Row="1" x:Name="llsContacts" ItemsSource="{Binding}" SelectionChanged="llsContacts_SelectionChanged" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<ListBoxItem local:TiltEffect.IsTiltEnabled="true">
<Grid Margin="0,0,0,10" >
<TextBlock Text="{Binding COLUMN_NAME, Mode=TwoWay}" FontFamily="Segoe WP" FontSize="28" Margin="77,0,0,0" />
<TextBlock Text="{Binding Path=COLUMN_NUMBER, Mode=TwoWay}" FontFamily="Segoe WP Light" FontSize="17" Margin="77,33,0,0"/>
</Grid>
</ListBoxItem>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
<!-- more 2 grids with contents -->
</Grid>
CS:
public ObservableCollection list;
public Main()
{
InitializeComponent();
list = new ObservableCollection<MyClass>(GetDataFromDatabase);
llsContacts.DataContext = list;
}
When I insert or remove something on DataBase, I alter on the list too:
list.Add(newData);
Am I doing something worng??
Reading this article: Frame rate counters in Windows Phone, I noticed that when this problem happens, some of the numbers that are on the side of the screen when debugging, stops changing...
They stops like this:
User Interface Thread FPS: 000
Texture Memory Usage: 007181
Surface Counter: 050
Intermediate Texture Counter: 002
Does this numbers means something?
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.
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>