Hierarchical Template Formatting Problems / Questions - xaml

I have a couple of questions about hierarchical template formatting for a TreeView. This image will illustrate:
I want to remove the extra space between the top of the type and the border.
I want to center the icon between the two lines of type
I want to add a thousands comma. I've tried this but there is a problem with adding a comma with a bound data.
Here is the XAML code for the third level:
<HierarchicalDataTemplate
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Height="42" Width="auto" >
<Grid Height="41" HorizontalAlignment="Left" Margin="0,0,0,0" Name="grid1" VerticalAlignment="Top" Width="auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Image Source= "{Binding XPath=UnitIcon}" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Left" Stretch="None" OpacityMask="White"></Image>
<Label Content="{Binding XPath=UnitName}" Height="54" HorizontalAlignment="Left" Name="label4" VerticalAlignment="Top" FontFamily="Smythe" FontSize="18" Margin="0,0,0,0" Grid.RowSpan="3" Grid.Column="2" Grid.ColumnSpan="3"/>
<Label Content="Strength:" FontFamily="Amaltea WF" FontSize="12" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="2" Grid.Row="2"/>
<TextBlock Text="{Binding XPath=UnitStrength, ConverterParameter=N0}" Margin="0,0,0,0" FontFamily="BauderieScriptSSK Bold" FontSize="18" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3" Grid.Row="2"/>
</Grid>
<Line X1='0'
X2='200'
Y1='0'
Y2='0'
Stroke="Gray"
StrokeThickness='1' />
</Grid>
</HierarchicalDataTemplate>
Thanks in advance for the help!

Take the fixed height off the UnitName label. You've got grid cells, you don't want fixed heights. Part of that gap may be the line height from your font. Temporarily set Background="LightSkyBlue" on the label to see how much space the label itself is actually taking up.
Looks like VerticalAlignment="Center" on the image isn't having the desired effect because you've put conflicting fixed heights on everything. Your grid1 is fixed at 41 units high, but the unit name within it is 54 units high. The layout engine is doing its best to comply with the contradictory orders you're giving it.
Delete every fixed height in your XAML. Every one, no exceptions. Let things size themselves. If you absolutely must impose a fixed height on a control, consider putting its contents in a ViewBox, so the contents can dynamically size themselves without overflowing the container. Or not; that can look weird. But first get your relative layout working, and then start working on cramming it down into whatever limited space you've got for it.
When you're having trouble with XAML layout, the naive impulse is to add stuff. And worst of all, to add random stuff -- "I don't know what this property means or what its value means, but maybe if I add it on this control, it'll fix what's wrong with the other one!" -- at best, the stuff you add will be harmless.
Don't do that. Remove stuff instead, then build back up. Add one thing at a time and see what it does. And add nothing without first reading the documentation on it. Adding six random properties from Intellisense seems to take less time than looking up one property on MSDN, but that turns out not to be the case in practice, because the first approach is always guaranteed to be a total waste of time. It's like driving by closing your eyes and trying to steer by the feel of the obstacles you crash into.
You're assigning the right format string to the wrong property. Try this:
<TextBlock Text="{Binding XPath=UnitStrength, StringFormat=N0}"
Except whoops LOL ha ha that doesn't work with Binding.XPath, so I'm talking nonsense. And neither does this:
<Label Content="{Binding XPath=UnitStrength}" ContentStringFormat="N0" />
I suspect they're failing because you're giving them a string rather than an integer, but that's just a guess.
But this works.
public class IntToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int n = 0;
if (Int32.TryParse((string)value, out n))
{
value = n.ToString((String)parameter);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML. YOUR_NAMESPACE_HERE is the C# namespace where you defined the IntToStringConverter class. That doesn't necessarily have to be right there; it could be on the parent tag or any containing tag in this XAML file, including the root tag (Window or UserControl or ResourceDictionary). Putting it here makes the example more self-contained.
<HierarchicalDataTemplate
xmlns:local="clr-namespace:YOUR_NAMESPACE_HERE"
>
<HierarchicalDataTemplate.Resources>
<local:IntToStringConverter
x:Key="IntToString"
/>
</HierarchicalDataTemplate.Resources>
<!-- blah blah -->
<TextBlock
Text="{Binding XPath=UnitStrength, Converter={StaticResource IntToString}, ConverterParameter=N0}"
/>
Update
<Window.Resources>
<!-- stuff -->
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<!-- stuff -->
</Window.Resources>
And for the TreeView:
<TreeView
...
ItemTemplate="{StaticResource UnitTemplate}"
...
/>
But this works too, if a template is going to be used in only one place:
<TreeView
...
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Another Upate
Or finally, if you want to put all your data templates in a file of their own, you want to create a resource dictionary:
<Window.Resources>
<!-- If you're doing the merged thing, you have to explicitly have the
ResourceDictionary tag here.
-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DataTemplates.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- other resources maybe -->
</ResourceDictionary>
</Window.Resources>
DataTemplate.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ScenarioEditor"
>
<local:IntToStringConverter
x:Key="IntToString"
/>
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="SomeOtherTemplate"
>
<Grid Width="auto">
<!-- different stuff -->
</Grid>
</HierarchicalDataTemplate>
</ResourceDictionary>
Yet Another Update
So the tree we're looking at has multiple levels, with a different template for each level. There are two ways to do this, at least: If we had a tree of .NET classes with different child types, we could define "implicit templates" in a resource dictionary. They'd have a DataType attribute rather than x:Key, with the result that (for example) the template with DataType="{x:Type local:HQ}" would automatically be used to display any class instance of that type.
But you've got XML so that's not going to work. What you can do instead is give each HierarchicalDataTemplate its own ItemTemplate. For clarity, the following example omits ItemsSource and much else -- it only illustrates how we set up those parent/child template relationships.
<HierarchicalDataTemplate
x:Key="UnitTemplate"
>
<Grid>
<!-- Unit stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="CommanderTemplate"
ItemTemplate="{StaticResource UnitTemplate}"
>
<Grid>
<!-- Commander stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="HQTemplate"
ItemTemplate="{StaticResource CommanderTemplate}"
>
<Grid>
<!-- HQ stuff -->
</Grid>
</HierarchicalDataTemplate>
HQTemplate will be the treeview's ItemTemplate
<TreeView
...
ItemTemplate="{StaticResource HQTemplate}"

Related

Is there a way to wrap the content of a HorizontalStackLayout

Im trying to display some items, for which, right now, I'm using a HorizontalStackLayout.
They should be displayed horizontally, but instead of acting like this:
Where the thrid item is not displayed fully and the following Items are not displyed at all, they should be wrapped to the next line. Which would look like (or similar to) this:
Is this possible with a HorizontalStackLayout or is there any other View that could create an effect like this?
The xaml for the Stacklayout looks like this at the moment:
<HorizontalStackLayout Grid.Column="1" BindableLayout.ItemsSource="{Binding DisplayedUserActions}" Margin="10">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Border BackgroundColor="White" HeightRequest="150" MinimumWidthRequest="180" Margin="5">
<Border.StrokeShape>
<RoundRectangle CornerRadius="20,20,20,20"/>
</Border.StrokeShape>
<Grid RowDefinitions="*,*">
<Border Grid.Row="0" StrokeThickness="2" Stroke="lightgray" BackgroundColor="AliceBlue" Margin="2">
<Border.StrokeShape>
<RoundRectangle CornerRadius="20,20,20,20"/>
</Border.StrokeShape>
</Border>
<Label Grid.Row="1" VerticalOptions="Center" HorizontalOptions="Center" Text="{Binding Title}" TextColor="Black"></Label>
</Grid>
</Border>
</DataTemplate>
</BindableLayout.ItemTemplate>
</HorizontalStackLayout>
StackLayout does just that, it stacks. Be it Horizintally or vertically, it stacks one item after another. It will never make an additional row if horizontal, or another column if vertical.
The FLexLayout however does have a Wrap property for this exact scenario. Couple with the FlexDirection you should be able to wrap it any which way.
Depending on how you want to display your items, between all the different layouts available, you should be able to find one that suits your needs.

Xamarin Forms Rowspan in CollectionView

I have a problem.
I created this CollectionView with a few dummy trades, that looks like this right now:
Now this is almost like I want it, except for 1 thing: I want the last column to get a rowspan over both the rows, like this:
Now if this was a regular Grid, I could do it with Grid.RowSpawn, but it is in a CollectionView, because I can have a lot of trades. The downside of the CollectionView is that each row is a different Grid, so they are actually not connected! Here is my code right now:
<CollectionView ItemsSource="{Binding agentOrderList}" Margin="0" HeightRequest="450">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid RowSpacing="0">
<StackLayout Orientation="Vertical">
<StackLayout HorizontalOptions="FillAndExpand" HeightRequest="1" BackgroundColor="White"/>
<Grid RowSpacing="0" Margin="5,0,5,0">
<Grid.RowDefinitions>
<RowDefinition Height="21" />
<RowDefinition Height="21" />
<RowDefinition Height="4" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65" />
<ColumnDefinition Width="95" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="82" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Text="{Binding Date}" FontAttributes="Bold" TextColor="#00D8FF" FontSize="18" VerticalOptions="CenterAndExpand"/>
<Label Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Text="{Binding Action}" TextColor="White" FontSize="18" VerticalOptions="CenterAndExpand"/>
<Label Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Text="{Binding Coin}" TextColor="White" FontSize="18" VerticalOptions="CenterAndExpand"/>
<Label Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" Text="{Binding Price}" TextColor="White" FontSize="18" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="End"/>
<Label Grid.Row="0" Grid.Column="4" Text="{Binding ProfitUSDT}" TextColor="{Binding ProfitColor}" FontSize="18" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="End"/>
<Label Grid.Row="1" Grid.Column="4" Text="{Binding ProfitPerc}" TextColor="{Binding ProfitColor}" FontSize="18" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="End"/>
</Grid>
</StackLayout>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Now what is the best way to achieve this? Do I need to make a different view?
Please let me know!
You can't have data cross over between cells in a ListView, so I think you will need to make each list item have a two row grid, so then you can have the last column span two rows.
However, I am confused. Your XAML code does not seem to match the screen shot of one cell. Your XAML code only seems to assign 5 columns, but I see 6 in your screen shots?
IN any case, you are correct, you will need to use one grid to display the Buy and Sell data so that that last column can span 2 rows.
UPDATE: Based on comments below, it seems a DataTemplateSelector may be required here. See: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector
Partial extract from above link:
A data template selector enables scenarios such as a ListView binding
to a collection of objects, where the appearance of each object in the
ListView can be chosen at runtime by the data template selector
returning a particular DataTemplate.
Creating a DataTemplateSelector A data template selector is
implemented by creating a class that inherits from
DataTemplateSelector. The OnSelectTemplate method is then overridden
to return a particular DataTemplate, as shown in the following code
example:
public class PersonDataTemplateSelector : DataTemplateSelector
{
public DataTemplate ValidTemplate { get; set; }
public DataTemplate InvalidTemplate { get; set; }
protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
{
return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
}
}
The OnSelectTemplate method returns the
appropriate template based on the value of the DateOfBirth property.
The template to return is the value of the ValidTemplate property or
the InvalidTemplate property, which are set when consuming the
PersonDataTemplateSelector.
An instance of the data template selector class can then be assigned
to Xamarin.Forms control properties such as ListView.ItemTemplate. For
a list of valid properties, see Creating a DataTemplate.
Limitations
DataTemplateSelector instances have the following limitations:
The DataTemplateSelector subclass must always return the same template
for the same data if queried multiple times.
The DataTemplateSelector subclass must not return another DataTemplateSelector subclass.
The DataTemplateSelector subclass must not return new instances of a
DataTemplate on each call. Instead, the same instance must be
returned. Failure to do so will create a memory leak and will disable
virtualization.
On Android, there can be no more than 20 different
data templates per ListView.
Consuming a DataTemplateSelector in XAML
In XAML, the PersonDataTemplateSelector can be instantiated by
declaring it as a resource, as shown in the following code example:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Selector;assembly=Selector" x:Class="Selector.HomePage">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="validPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="invalidPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
ValidTemplate="{StaticResource validPersonTemplate}"
InvalidTemplate="{StaticResource invalidPersonTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
This page level ResourceDictionary defines two DataTemplate instances and a
PersonDataTemplateSelector instance. The PersonDataTemplateSelector
instance sets its ValidTemplate and InvalidTemplate properties to the
appropriate DataTemplate instances by using the StaticResource markup
extension. Note that while the resources are defined in the page's
ResourceDictionary, they could also be defined at the control level or
application level.
The PersonDataTemplateSelector instance is consumed by assigning it to
the ListView.ItemTemplate property, as shown in the following code
example:
<ListView x:Name="listView" ItemTemplate="{StaticResource personDataTemplateSelector}" />
At runtime, the ListView calls the
PersonDataTemplateSelector.OnSelectTemplate method for each of the
items in the underlying collection, with the call passing the data
object as the item parameter. The DataTemplate that is returned by the
method is then applied to that object.

XAML Master / Template pages with MVVM

Is there a way to create master / template pages in XAML (for UWP applications)?
The problem I'm trying to solve:
I have an application with a lot of similar sites, where only the content changes slightly but not the Buttons and the Layout. Example:
<Page
DataContext="{Binding WebpageViewModel, Source={StaticResource Locator}}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Edit Webpage" Style="{StaticResource BigTexBlock}" />
<ScrollViewer Style="{StaticResource ContentScrollViewer}" Grid.Row="1" VerticalScrollMode="Enabled">
<StackPanel Margin="10,0">
<webpage:EditWebpage DataContext="{Binding }" />
</StackPanel>
</ScrollViewer>
</Grid>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.PrimaryCommands>
<!-- more buttons -->
<AppBarButton IsCompact="True" Command="{Binding SaveEntryCommand}" Icon="Save" Label="Save" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
</Page>
Only three parts of this template will change; the ViewModel in the DataContext, the Text of the TextBlock, and the UserControl which contains the editable fields.
As this is an application with a lot of CRUD happening with simple Entities the amount of code to be repeated over and over again is a lot if I keep "solving" the problem like this. In the separated business logic I could avoid this problem with inheritance, but I'm struggling to find a elegant solution in XAML. 
Is there a way to refactor this so I may have a "Template Page"?
I like how for example twig has solved this problem: http://twig.sensiolabs.org/. You define a master/template page and override parts of it in the children templates.
Important to me is that
I don't break the MVVM pattern.
I don't want to hide/show UserControls in one "Main" XAML as the amount of different entities may become quite large
I want navigation happening between the pages that the user sees the expected animations, and it does not break the separated view code I already have
There isn't a master page or template mechanism that other technologies, like MVC, have. But you can use frames and navigation to do what you're looking for.
You could keep the page defined the way you currently have it. All of the fixed elements on the page are in the layout. Now instead of using a UserControl for your specific edit UI, replace that with a frame.
<StackPanel Margin="10,0">
<Frame Name="EditFrame" DataContext="{Binding }" />
</StackPanel>
Now when you navigate to the Main Edit page, also pass the type for the view you want in the frame. Then on your OnNavigatedTo override for the main page, you can navigate the frame to the view type as the parameter.
You can also use the EditFrame to page through multiple editing pages, like if you had a wizard UI with Next and Previous buttons, without leaving the main page.
You can either do this in your OnNavigatedTo method or modify your NavigationService to be able to handle this behavior.
I have solved this problem with the approach suggested by https://stackoverflow.com/a/43170663
my NavigationService
//get the current frame
var frame = (Frame)Window.Current.Content;
//navigate to the generic AddEntry page
frame.Navigate(typeof(AddEntryPage), new NavigationParameter() { /* set props needed */ });
my xaml (my "master page") looks now like this (using a Frame now):
<Page
x:Class="Famoser.Bookmarked.Presentation.Universal.Pages.Entry.Webpage.AddEntryPage"
mc:Ignorable="d"
d:DataContext="{Binding WebpageViewModel, Source={StaticResource Locator}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Name="Title" Grid.Row="0" Text="Add "/>
<ScrollViewer Grid.Row="1">
<StackPanel Margin="10,0">
<Frame x:Name="EntryFrame" />
</StackPanel>
</ScrollViewer>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.PrimaryCommands>
<!-- more app buttons -->
<AppBarButton IsCompact="True" Command="{Binding SaveEntryCommand}" Icon="Save" Label="Save" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
</Page>
and in the code behind in the navigation event I set the properties passed by my NavigationService
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is NavigationParameter pm)
{
DataContext = SimpleIoc.Default.GetInstance(pm.ViewModelType);
Title.Text = "Add " + pm.Name;
EntryFrame.Navigate(pm.EditFrameType);
}
}
the full project in on github: https://github.com/famoser/Bookmarked

Biding with Pivot control on Windows Phone 8 with MVVM

I finally got my pivot control to work using MVVM in a wp8 app but I still have a question in regards to binding as thought as it works, and I could accept it as is, I'm not happy with the outcome and I'm trying to understand why this is happening. My DataContext, MainViewModel, contains multiple other ViewModels.
Scenario 1:
If I define the DataContext in the Grid (layout), and I assign the itemsSource for the pivot headers to QuickSearchTabs ViewModel and this get built ok but the listbox I have defined inside the pivotitem doesn't which is assigned the QuickSearchButtons ViewModel doesn't get built. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource MainViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" FontSize="{StaticResource PhoneFontSizeSmall}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}">
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
Scenario 2:
If I define the DataContext in the Grid (layout) and define the same DataContext within the listbox tags, it will build my header and my listbox BUT it will call my viewModel which is assigned to the ItemsSource of the listbox, multiple times. To be exact, it will call it the same number of time as the number of pivots I have. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource CriteriaViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}" >
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}" DataContext="{StaticResource CriteriaViewModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
As mentioned, this works, and it's not affecting me in anyway as the correct data is always displayed.
I can somehow see what's happening but why on earth would the ItemsSource be set for each of the defined pivot headers. Surely, the only important one is the one coming into visibility!
I don't know if Pivots are suppose to be used the way I'm using them. It seems, from what I've seen so far that normally a view is assigned to each PivotItem. This is not how I want my solution to work!
I just want numerous headers which are used to groups things in a specific manner and whatever is displayed under each is build dynamically but on the same view i.e. list of buttons and label.
Any ideas on how I could get scenario 1) to work and if I'm stuck with scenario 2, how to stop it from being triggered based on the number of pivot header items?
Thanks.
Problem solved!
The QuickSearchTabs was an observable collection of QuickSearchTab when it should have been an observable collection of ViewModel i.e. QuickSearchTabViewModel and within this viewModel, it will load the observable collection of relevant QuickSearchButtons for each of the tab.
Having a QuickSearchTabViewModel provides more flexibility and it will allow access to the current tab (header), and other relevant properties including everything maintain within each of these tabs such as, in my case the buttons.
Hope this helps.

Binding TextBlock foreground to Global.cs variable in xaml

I've been trawling the web trying to find a similar problem but can't find anything that solves my problem.
I have a static class holding global variables, some of these are colour variables which I want to be able to bind in my xaml controls such that I only have to change one variable to change the lot (the reason for global variables).
The class namespace is MyApp.Assets.Resources the class name is Global(.cs).
In my class I have variables named DEFAULTCOLOR, OKCOLOR and ALARMCOLOR.
My xaml:
<UserControl
<!-- ... -->
xmlns:custom="clr-namespace:InspectionDB.Assets.Resources"
>
<UserControl.Resources>
<custom:Global x:Name="global"/> <!-- THIS GIVES AN ERROR SEE BELOW-->
<common:HierarchicalDataTemplate x:Key="Level1" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Type, Converter={StaticResource localTreeImgConverter}}"/>
<TextBlock {Binding...} />
<StackPanel Orientation="Horizontal" Visibility="{Binding Type, Converter={StaticResource localStatusVisibilityConverter}}">
<TextBlock Margin="5,0, 0,0" Text="[ " Foreground="{Binding DEFAULTCOLOR, Source={StaticResource global}}" />
<TextBlock Text="{Binding Critical}" Foreground="{Binding ALARMCOLOR, Source={StaticResource global}}"/>
<TextBlock Text=" | " Foreground="{Binding DEFAULTCOLOR, Source={StaticResource global}}"/>
<TextBlock Text="{Binding OK}" Foreground="{Binding OKCOLOR, Source={StaticResource global}}"/>
<TextBlock Text=" ]" Foreground="{Binding DEFAULTCOLOR, Source={StaticResource global}}"/>
</StackPanel>
</StackPanel>
</common:HierarchicalDataTemplate>
</UserControl.Resources>
<Grid>
<!-- Where the hierarchical template is used -->
</Grid>
</UserControl>
The part in the Resources throws an error as well as the binding:
Unable to cast object of type 'ApplicationProxy' to type 'Microsoft.Expression.DesignModel.DocumentModel.DocumentNode'.
What is wrong with my code and how can I get it to work?
I found what my problem was, and therefore why I couldn't find any similar situation.
I had public class Global : App - don't ask me why, I'm sure there was a valid reason long ago but it meant it had some kind of funky circular referencing going on.
Problem solved.