Accessing named controls from page resources - windows-runtime

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

Related

Create Tab Items and Tab Content dynamically using Orchestra/Catel

I am attempting to create a tabbed interface using Orchestra/Catel. I load the tabs definitions into a TabInfo class. Those work fine - a tabbed interface is created with the correct tab descriptions. In the content for each tab, I want to create a list of buttons - again loaded into a ButtonInfo class. When a tab is selected, the SelectedTab property is used to select the correct list of buttons (ShowButtons).
I have traced the program and when I click on a tab, the correct collection of buttons is in ShowButtons, but nothing shows up in the tab content. I did get this to work in a normal MVVM program, but without the tabs. I used a listview to show my tabs and an ItemsControl to show the buttons.
Belows is my XAML code for the tabs and my SelectedTab logic for pulling the buttons.```
<Grid>
<orccontrols:TabControl LoadTabItems="LazyLoading" ItemsSource="{Binding TabInfo}" SelectedItem="{Binding SelectedTab}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabDesc}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding ShowButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding ButtonDesc}"
MinWidth="150"
Height="30"
FontSize="12"
FontWeight="Bold"
Margin="0,15,25,10"
Padding="5,1">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding OracleJob}" Value="0">
<Setter Property="Button.Background" Value="DarkSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</TabControl.ContentTemplate>
</orccontrols:TabControl>
</Grid>
And the code for populating ShowButtons:
public void OnSelectedTabChanged()
{
int _selectTab = SelectedTab.TabKey;
var _showButtons = ButtonInfo.Where(i => i.ButtonTab == _selectTab);
ObservableCollection<ButtonRecord> _btn = new ObservableCollection<ButtonRecord>(_showButtons);
ShowButtons = _btn;
}
Any help is greatly appreciated. I am a beginner with Orchestra/Catel, so I am probably missing the best way to do this.
I recommend to split up the issue from Orchestra / Catel. Orchestra allows you to provide a view as shell, but this view can live on it's own (the only thing Orchestra does is place it inside the correct location inside the shell). By making this problem unrelated to Orchestra, it makes it a bit easier for us to solve.
Next up, I recommend looking into the Catel docs. There is a full example on how to show a shell with tabs with closable tab buttons, see https://docs.catelproject.com/vnext/tips-tricks/mvvm/using-tabbed-interface-with-mvvm/

Remove commandbar ability to expand WP 8.1

I want to remove the ability to expand the command bar. (no dots)
Is this possible?
AFAIK it's not possible to remove the ellipsis (those three dots) from application bar.
If you have no Secondary commands then ellipsis will just show labels of your app bar buttons. Taking a look at ClosedDisplayMode you have only two values: minimal and compact - which means that you cannot have app bar opened with labels without ellipsis.
Other way may be to build your own control which will immitate application bar - then you can put there what you want.
As Romasz Said it's not possible to remove the three dots. But you can create a template smiler to application bar, something like that :
<Grid x:Name="LayoutRoot" >
<Grid VerticalAlignment="Bottom" Background="#FF1F1F1F" >
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" >
<AppBarButton x:Name="test1" Icon="Play"/>
<AppBarButton x:Name="test2" Icon="ReShare"/>
</StackPanel>
</Grid>
</Grid>
And this will give you :

Access to StackPanel defined in DataTemplate

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;
}

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

Force GridView To Create Not Recycle Controls

I have a GridView in a windows store app that has an ItemContainerStyleSelector. Within the style is an Image control that has a custom dependency property to set the source (This is so I can get a handle on the Image and hook up to the unloaded event).
My issue is the Image is never unloaded and seems to be reused. This means that when I set the source, the image is set on other items in the GridView as well (For Example I have an object which has no image but after scrolling away and then back again it has an image from another object).
I've tried to set virtualization mode to standard where I can but it doesn't help. Any ideas would be greatly appreciated.
Here is the Image that is contained in the style. This is passed to a method "OnRemoteURISourceChanged" when set. I'd expect a different image control whenever the method is called but this is not the case.
<Image x:Name="BackgroundImage" DataContext="{Binding CurrentBackdrop}" helpers:ImageExtensions.RemoteURISource="{Binding Uri}" Stretch="UniformToFill"/>
And here is my GridView
<GridView x:Name="ItemsGrid" Grid.Row="1" ItemsSource="{Binding BrowseResults}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Margin="20,0,20,0"
IsItemClickEnabled="True" ItemClick="ItemsGrid_ItemClick" VirtualizingStackPanel.VirtualizationMode="Standard">
<GridView.ItemContainerStyleSelector>
<controls:UPnPCDStyleSelector CDObject="{StaticResource somestyle1}" Container="{StaticResource somestyle2}" Item="{StaticResource somestyle3}"/>
</GridView.ItemContainerStyleSelector>
<GridView.ItemsPanel>
<ItemsPanelTemplate VirtualizingStackPanel.VirtualizationMode="Standard">
<WrapGrid Orientation="Vertical" VirtualizingStackPanel.VirtualizationMode="Standard"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
UPDATE: The issue appears to be the WrapGrid. If I change this to a VirtualizingStack Panel and set the VirtualizationMode to Standard then everything works as expected but obviously my items then only appear on one line and not multiple lines as I wish.
How do I set the virtualization mode of a WrapGrid?
Is there a chance your helpers:ImageExtensions.RemoteURISource doesn't clear the Image.Source when either your CurrentBackdrop property or its Uri property value is null?
Are you sure the task which is loading the img source returns to default ui context when awaiting? I don't think it is a good idea to set Image.Source property form code. The better solution would be to create a custom observable task class and bind im source to it's result. In the background you can call the task. Do you need the control to be Image? Because if it would be a control with template, it would be easier for you to do that. I can send you the class which does that if you want to.