Access to StackPanel defined in DataTemplate - windows-phone-8

I've got a LongListSelector for which I select the appropriate DataTemplate based on data I receive according to user's selections.
There are 3 of those DataTemplates which I define in the page's resources and set the appropriate one -just before populating my LongListSelector- using:
RoutesLongListSelector.ItemTemplate = Resources["SecondItemTemplate"] as DataTemplate;
There is an element in these DataTemplates -a StackPanel- where I add some children after populating my list.
<StackPanel x:Name="MyStations" Grid.Column="1" Grid.Row="1">
</StackPanel>
So, when I try to use its name in order to add children [MyStations.Children.Add(...)] I get this error: 'MyStations' does not exist in the current context.
I tried to set one of the Templates as default in the page's ContentPanel but I still get the same error.
Seems to be a minor issue but I couldn't think of something.
Any suggestions?

You can't access UI elements of DataTemplete with their Name property, i.e. x:Name. You can use it's loaded event to access it. Please be specific on your requirement.
<StackPanel x:Name="MyStations" Grid.Column="1" Grid.Row="1"
Loaded="MyStations_Loaded" />
private void MyStations_Loaded(object sender, RoutedEventArgs e)
{
var _StackPanel = (StackPanel)sender;
}

Related

Can we use longlistselector inside a popup in Windows phone 8?

How to use longlistselector inside a popup control?
If not possible, then any other way to show longlistselector/listbox as a popup ?
As a popup you can you CustomMessageBox. Instances of CustomMessageBox have property Content, that has no differences from the Content property of any other content controls. So you can put there LongListSelector or ListBox or whatever you want (even Pivot and Panorama), than call Show method. CustomMessageBox will close if user'll click one of the 2 default buttons, but you can hide them (properties IsLeftButtonEnabled and IsRightButtonEnabled) and close CustomMessageBox by your own logic by calling Dismiss method. There is a couple of useful events: the most useful is Dismissed, that raises right after CustomMessageBox get closed (dismissed), its handler contains DismissedEventArgs, that has result of users choiсe (right or left button was chosen, if they were on the screen) and of course sender (CustomMessageBox). If you want some logic after CustomMessageBox closing, use Dismissed event, Show method won't stop program flow.
This is the easiest way to show something. It's not a popup, but it behaves like it.
But if you wont to use popup ifself, there is Child property for you, put there Grid, and ListBox inside the Grid. But you have to set the values of the Width and Height of popup Child.
You can create a new Page and simply put your LongListSelector in it.
For example (Page is called MyPopupPage):
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<con:LongListSelector x:Name="LongListSelector">
<con:LongListSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</con:LongListSelector.ItemTemplate>
</con:LongListSelector>
</Grid>
Then fill it with whatever you want (Refer to: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj244365(v=vs.105).aspx)
In your MainPage (the page which should open the popup):
Create an object of type Popup like:
Popup LLSPopup = new Popup();
And create a Method to set the MyPopupPage as the overlay of the popup:
private void ShowPopup()
{
MyPopupPage ovr = new MyPopupPage();
this.LLSPopup.Child = ovr;
this.LLSPopup.IsOpen = true;
}

How to ReStyle Pivot Header

I have recently come across an interesting app and I would like to somewhat modify my solution to resemble their Pivot Header Template. The app can be seen here http://www.windowsphone.com/en-us/store/app/fhotoroom/acad1eed-3149-4b6c-bc4b-8567f409e3e0
where as a user swipes between pivot items the icons in the top right are highlighted accordingly. I have referenced a solution where the icons are paths and as the user swipes between pivot items the icons change colors. The only thing is, I would like to show icons on the right, while on the left the name changes to the respective pivot header name (but only show a single name at a time). I'm kind of lost on how to start this. My thoughts were, get a pivot style copy from blend into the apps page, and then somehow retemplate this so that icons show on the right while the name is on the left. Am I thinking of this correctly? How might I start changing the style to reflect something like this? Is there a better way?
I think pivot header doesn't match behavior that you want to achieve. By default every single pivot item has its own header, and if I don't misunderstand, in this case you got one header for whole pivot control, with displayed text and highlighted icon in the header changes according to active pivot item.
If that is the case, it will be easier to remove the pivot header. Then create a single element on top of the page as pivot header. Bind selected pivot index to a property in model. Then bind the text in the header element to a property that return different string based on selected pivot index. Use similar data-binding concept for highlighting icon (you already have referenced solution for this one). Example :
<Grid Background="DarkBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding HeaderText}" Foreground="White"
FontSize="40" Margin="10,5,5,5"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<!--Some icons here-->
....
</StackPanel>
</Grid>
<phone:Pivot SelectedIndex="{Binding PivotIndex, Mode=TwoWay}" Grid.Row="1">
<phone:PivotItem>
...
</phone:PivotItem>
....
</phone:Pivot>
And in the viewmodel :
private int _pivotIndex;
public int PivotIndex
{
get { return _pivotIndex; }
set { _pivotIndex = value; NotifyPropertyChanged("PivotIndex"); }
}
public string HeaderText
{
get { return GetHeaderByIndex(PivotIndex); }
}
private string GetHeaderByIndex(int pivotIndex)
{
switch (pivotIndex)
{
case 0:
return "#recent";
case 1:
return "#favorite";
default:
return "";
}
}
How about that, or is that not the case?
NOKIA made a really good tutorial how to do this. You can go trough the tutorial or just download the code at the bottom of the page.
Tabbed interface with Pivot animation for Windows Phone

How to free memory hold by images in data template in windows phone 8 App?

I have a longlistselector for which I have a data template that defines the type of items to be added to the list. The data template has an Image control whose source is binded with path dynamically, thus each item in list has an associated Image Control. The problem I face is that these Image control never free the memory they occcupy resulting in out of memory exception. On normal scenario I set bitmapImage.UriSource=null to deallocate the memory associated with the bitmap But can't find a way to do so in this scenario. Here is the xaml code for the longlistselector and the data template associated with it..
Data Template
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="MediaItemTemplate">
<Canvas VerticalAlignment="Top">
<Border BorderBrush="#FF4791CA" BorderThickness="3">
<Image Height="100" Width="100" VerticalAlignment="Top" Grid.RowSpan="2" Stretch="UniformToFill">
<Image.Source>
<BitmapImage UriSource="{Binding path}" CreateOptions="BackgroundCreation" DecodePixelHeight="50" DecodePixelWidth="50"/>
</Image.Source>
</Image>
</Border>
<Image Source="/Icons/check.png" Height="16" Width="16" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top" Margin="80,7,7,0" Canvas.ZIndex="100" OpacityMask="Black" Visibility="{Binding visibility}" Name="checkImage" >
</Image>
</Canvas>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
LonglistSelector
<phone:LongListSelector
Tap="ListMedia_Tap"
x:Name="ListMedia"
HorizontalAlignment="Left"
Height="624"
VerticalAlignment="Top"
Width="436"
Background="Transparent"
ItemTemplate="{StaticResource MediaItemTemplate}"
LayoutMode="Grid" GridCellSize="120,120"/>
I am very new to windows phone programming, What basically I want to do is to develop kind of image browser experience. Please Help me out with ways to deallocate the memory. In case I am doing it completely wrong please correct me or suggest better ways to achieve the same functionality. Thanx in advance...
A solution I've found to handle this case is making a custom control to automatically set the urisource to null:
public class SafePicture : System.Windows.Controls.ContentControl
{
public SafePicture()
{
this.Unloaded += this.SafePictureUnloaded;
}
private void SafePictureUnloaded(object sender, System.Windows.RoutedEventArgs e)
{
var image = this.Content as System.Windows.Controls.Image;
if (image != null)
{
image.Source = null;
}
}
}
Then, just wrap all your pictures in that control:
<my:SafePicture>
<Image Source="{Binding Path=path}" />
</my:SafePicture>
By default Windows Phone stores messages downloaded from a Uri in memory to save having to load them again. (It's a crude form of caching.)
To free the memory used by these images you needed to explicitly free all references to them. See MSDN: Image Tips for Windows Phone 7 for more details
When scrolling with your code (without using Loaded), then images are lost after scrolling down and returning to the top of the list (speed no matter). While using Loaded, scrolling wokrs okay: it is possible to scroll down and return to the top, (debugger shows that Unloaded and Loaded are called), and images are there. However, when moving to another page (i have master-detail pages), they are mixed up.

How to force keyboard not overlap the stack panel

I am new to WP development and trying to get hands-on.
If you look at wallet pin screen, focus is automatically set to textbox so that user can start typing and also the keyboard does not hides/overlaps done & cancel button.
Also, If you hit back key, those buttons remain at bottom as shown below.
I am also trying to have same kind of UI. However, In my case
I am not able to set focus to textbox as soon as page is loaded. I
can't get .Focus() method of textbox in OnNavigatedTo event. Where
should i do this ?
When i manually tap textbox to enter a value, the keyboard overlaps
my stackpanel containing 'save' & 'cancel' button as shown below. I
don't want this to happen. Instead the screen should look like as
shown in 2nd image.
Below is the XAML code i tried.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock Name="txtLimit" TextWrapping="Wrap" Text="Enter the value" Style="{StaticResource PhoneTextSubtleStyle}"/>
<TextBox AcceptsReturn="True" InputScope="Number" />
</StackPanel>
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center" Orientation="Horizontal" >
<Button Content="save" Width="200" />
<Button Content="cancel" Width="200"/>
</StackPanel>
</Grid>
For setting the focus for first time navigation you apparently have to set this in the Loaded event handler.
For back navigation (from when you application is switched away), the one in OnNavigatedTo will fire as you'd expect.
// Constructor
public MainPage()
{
InitializeComponent();
this.Loaded += (sender, args) => this.textBox.Focus();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.textBox.Focus();
}
However you will need to add your buttons to the ApplicationBar to show below the on-screen keyboard.
However the SDK doesn't allow use of rectangular buttons in the application bar, only icon buttons.
In the OnNavigatedTo method, can you try to use the Dispatcher like this :
Dispatcher.BeginInvoke(()=>{
this.textBox.Focus();
});
And, as pointed out, you can NOT have rectangular buttons in the appBar but you can use standard one (like the linked in button for example).

Accessing named controls from page resources

I needed to access to the ActualWidth of a Border that didn't have a specified Width. I have been told that I can't do that on WinRT so I used a proxy from Florian-Gl (from here).
The thing is that I need to create that proxy on the page's resource like this:
<Page.Resources>
<utils:ActualSizePropertyProxy Element="{Binding ElementName=noteBorder}" x:Name="proxy" />
</Page.Resources>
The problem is that I don't have access to that noteBorder element from the resources, but I have access to pageRoot that is the Page itself.
I guess that I can play with ElementName / Path to get access to noteBorder.
But there is some curious stuff:
The structure is something like:
Page (pageRoot) > Grid > ListView > ListView.ItemTemplate > Grid > Border (noteBorder)
So, If I create the proxy at the same level of the border, It won't run but If I change the ListView to a ItemsControl, it will run and works as expected.
If having it at the same level of the border I change the ElementName to pageRoot it will run at least.
So, It won't run if I put noteBorder (even when I have access to it) if I'm using a ListView, but will work on a ItemsControl, On the other hand, If I have pageRoot it works all ways.
So the question is: Is there a way to access noteBorder from resources? Or maybe a way to access it from another place but working :P
You should be using an Item Template --
By the time you get to
pageRoot) > Grid > ListView or Items Control
At this point in the structure, you're at the element you really want to get at, which is the container of the items that will need the border you are trying to access.
You should define an Item Template and assign the ListView's (or ItemsControl's) ItemTemplate property via binding.
<ListView x:Name="myListView" DataContext="{Binding ToElementIfNotInheritedFromParent}" ItemsSource="{Binding ViewModelListBeingBoundTo}" ItemTemplate="{Binding Source={Static Resource MyCustomItemTemplate}}" />
Where MyCustomItemTemplate is something like
<DataTemplate x:Name="MyCustomItemTemplate">
<Border x:Name="myBorder" >
<StackPanel>
<TextBlock Text="{Binding Path=Title}" />
<TextBlock Text="{Binding Path=FirstProperty}"/>
<TextBlock Text="{Binding Path=SecondProperty}"/>
</StackPanel>
</Border>
</DataTemplate>
Then In your Codebehind (or if ViewModel use the code behind to pass the ListView object to the ViewModel)
DataTemplate dt = this.myListView.Items[indexOfChoice].ItemTemplate as DataTemplate;
Border b = dt.LoadContent() as Border;
int actualWidth = b.AcutalWidth
OR
You can create a FindControl() method that runs recursively to extract the actual control within the border, for instance if you wanted to access one of the Textboxes.
The code for that is here:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a612f5a6-e05e-4b68-a813-893eeda159cc