Hub with dynamic HubSections with GridViews and DataBinding - c#

I would like to create a Hub with several HubSections via code. Each HubSection owns a single GridView so it look like every HubSection is a table (fullscreen) and I swipe left/right to view every table.
In my XAML page is only Hub the other stuff should be done by code. The HubSections should be created at runtime. For this I use a local settings storage to save some information about this, like how many HubSections etc.
Creating new HubSections is no problem but I'm stuck at adding a GridView to each HubSection because I don't understand the logic here. It looks like I have to add a DataTemplate and a GridView but my attempts all failed.
Note: each GridView has also it's own databinding from a Observable Collection.
So how to add a (?DataTemplate?) GridView with databinding to a HubSection ?

With a DataTemplate you build your layout. I have used in a Project following template to show a few data per day and create one Section for each day:
<Page.Resources>
<CollectionViewSource x:Name="HubViewModel"/>
<DataTemplate x:Key="DataTemplate">
<Grid Background="Transparent" Width="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,20">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" HorizontalAlignment="Center">
<TextBlock Text="{Binding SumShipmentsSA}" Style="{ThemeResource HeaderTextBlockStyle}" TextAlignment="Center" TextWrapping="NoWrap"/>
</StackPanel>
<StackPanel Grid.Row="1" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock x:Uid="SummaryHubNat" Text="National" FontSize="10" Width="100" VerticalAlignment="Center" Margin="0,0,20,0"/>
<TextBlock Text="{Binding CountShipmentsNationalSA}" Style="{ThemeResource BodyTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock x:Uid="SummaryHubInt" Text="International" FontSize="10" Width="100" VerticalAlignment="Center" Margin="0,0,20,0"/>
<TextBlock Text="{Binding CountShipmentsInternationalSA}" Style="{ThemeResource BodyTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock x:Uid="SummaryHubCharter" Text="Charter" FontSize="10" Width="100" VerticalAlignment="Center" Margin="0,0,20,0"/>
<TextBlock Text="{Binding CountShipmentsCharterSA}" Style="{ThemeResource BodyTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</Page.Resources>
.
.
<Hub x:Name="MainHub" DataContext="{Binding Source={StaticResource HubViewModel}}" Margin="0,0,0,20"/>
In the Code page I used the following method to create to the Section:
private void AddHubSection(IEnumerable<DaySummary> list)
{
if (list != null)
{
list = list.OrderByDescending(x => x.Date);
foreach (var item in list)
{
if (item.Date.Date.Equals(DateTime.Now.Date))
{
continue;
}
HubSection hubSection = new HubSection();
TextBlock headerTextBlock = new TextBlock();
headerTextBlock.Text = item.Date.ToString("dddd dd.MMM");
headerTextBlock.FontSize = 15;
hubSection.Header = headerTextBlock;
hubSection.Margin = new Thickness(0);
object dataTemplate;
this.Resources.TryGetValue("DataTemplate", out dataTemplate);
hubSection.ContentTemplate = dataTemplate as DataTemplate;
hubSection.DataContext = item;
hubSection.DoubleTapped += HubSection_DoubleTapped;
MainHub.Sections.Add(hubSection);
}
}
}
I think the example can help you have fun while trying.

Related

Get UserControls dynamically via XamlReader.Load, IsLoaded is false at UI Elements

I try to save and load TabItems via XamlWriter and XamlReader at runtime so that the user can restore the previous session. Each TabItem consists of UserControls and standard WPF controls like grids,buttons and checkboxes.
It all works fine until I try to subscribe to events of let's say a button.
If I raise them manually with RaiseEvent() they work, but if I click on them nothing happens. Even if I set IsEnabled=false the button is displayed as enabled. LogicalTreeHelper.FindLogicalNode gives me the right button, but the Click event also won't trigger. The IsLoaded property is false, so I assume there has to be some underlying problem with the initialization.
Basically this is the code to read from the file
StreamReader sw = new StreamReader(file);
XmlReader xmlReader = XmlReader.Create(sw);
TabItem tabItem = (TabItem)XamlReader.Load(xmlReader);
.. and this to save each TabItem to a seperate xml file
foreach (TabItem tabItem in tabControlMain.Items)
{
StreamWriter sw = new StreamWriter(Path.Combine(path,tabItem.Name + ".xml"), false);
string savedTab = XamlWriter.Save(tabItem);
sw.Write(savedTab);
sw.Close();
}
Here is an example TabItem saved to a file
<TabItem IsSelected="True" Header="Test" Name="tabItem1" HorizontalAlignment="Left" VerticalAlignment="Top" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:womoc="clr-namespace:WeldOsMqttOpcClient;assembly=blabla">
<TabItem.HeaderTemplate>
<DataTemplate DataType="{x:Type TabItem}">
<TextBox Margin="0,0,30,0" Text="{Binding Path=.}" />
</DataTemplate>
</TabItem.HeaderTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<womoc:UcOverviewTabPage Autoconnect="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Name="gridParentOv">
<Grid Name="gridMqttOpcControls" Height="599.08" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<womoc:UcConnection Name="ucOpc" MinWidth="400" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<GroupBox Header="OPC [10.5.51.130]" Name="groupBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ScrollViewer>
<Grid Name="gridTextBoxesWithValues" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Name="rowLabel" />
</Grid.RowDefinitions>
<Label Background="#FF008000" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelConnected" Width="190" Height="26" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.ColumnSpan="2">Connected!</Label>
</Grid>
</ScrollViewer>
</GroupBox>
</womoc:UcConnection>
</Grid>
<Grid Name="gridConnection" MinHeight="30" HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
<Button Name="btnConnect" Width="55" Margin="100,0,0,10" HorizontalAlignment="Center" VerticalAlignment="Bottom" IsEnabled="False">Connect</Button>
<TextBox Name="tbIPAddress" Width="95" Height="18" Margin="0,0,100,10" HorizontalAlignment="Center" VerticalAlignment="Bottom" IsEnabled="False">10.5.51.130</TextBox>
<CheckBox Name="cbMqtt" Width="46" Height="15" Margin="20,0,0,10" HorizontalAlignment="Left" VerticalAlignment="Bottom" IsEnabled="False">Mqtt</CheckBox>
<CheckBox IsChecked="True" Name="cbOpc" Width="42" Margin="0,0,20,10" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsEnabled="False">Opc</CheckBox>
</Grid>
</Grid>
</womoc:UcOverviewTabPage>
</Grid>
</TabItem>
UcOverviewTabPage is one of my UserControls, in which there is for example a button. I try to subscribe to the events manually ->
public UcOverviewTabPage()
{
InitializeComponent();
cbMqtt.Checked += CbMqtt_Checked;
cbMqtt.Unchecked += CbMqtt_Unchecked;
cbOpc.Checked += CbOpc_Checked;
cbOpc.Unchecked += CbOpc_Unchecked;
btnConnect.Click += BtnConnect_Click;
var children = LogicalTreeHelper.FindLogicalNode(this, "btnConnect") as Button;
bool loaded = children.IsLoaded;
// -> FALSE
}
Bear in mind, creating new custom UserControls during runtime works perfectly. The problem only occurs when reading out of the XML file.
I except the UserControls or any other Controls to work like they do when created during runtime. What am I missing?

C# UWP Get Items in ListView's ItemTemplate

I am trying to access textblocks and textboxes in a listview, but cannot get them in C# code because they are inside an ItemTemplate and DataTemplate. Here is a sample of the XAML code:
<ListView x:Name="VehicleList" HorizontalAlignment="Center" Height="120" Margin="0" VerticalAlignment="Center" Width="1119" Background="{ThemeResource CheckBoxDisabledForegroundThemeBrush}" SelectionChanged="VehicleList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="VehicleGrid" Height="52" Width="1117" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="318*"/>
<ColumnDefinition Width="425*"/>
<ColumnDefinition Width="366*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Year" Grid.Column="0" TextWrapping="Wrap" Text="{Binding Year}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="321" FontSize="26.667"/>
<TextBlock x:Name="Make" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Make}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="425" FontSize="26.667" />
<TextBlock x:Name="Model" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Model}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="366" FontSize="26.667"/>
<TextBox x:Name="AddYear" Grid.Column="0" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="321" FontSize="26.667" Visibility="Collapsed"/>
<TextBox x:Name="AddMake" Grid.Column="1" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="425" FontSize="26.667" Visibility="Collapsed"/>
<TextBox x:Name="AddModel" Grid.Column="2" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="366" FontSize="26.667" Visibility="Collapsed"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Is there anyway to get the items inside the DataTemplate?
Your problem is generic to all XAML flavors, same in WPF and Silverlight. The problem is your DataTemplate. Keep in mind that XAML will inject the contents of your DataTemplate once for each item in your list. That means your names can only exist within the scope of an instance of your DataTemplate.
If you have do code behind for your template, you might do better by creating a UserControl. See below for an example:
<!-- most boiler plate code skipped -->
<UserControl x:Class="MyProject.VehicleListItem">
<Grid x:Name="VehicleGrid" Height="52" Width="1117" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="318*"/>
<ColumnDefinition Width="425*"/>
<ColumnDefinition Width="366*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Year" Grid.Column="0" TextWrapping="Wrap" Text="{Binding Year}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="321" FontSize="26.667"/>
<TextBlock x:Name="Make" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Make}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="425" FontSize="26.667" />
<TextBlock x:Name="Model" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Model}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="366" FontSize="26.667"/>
<TextBox x:Name="AddYear" Grid.Column="0" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="321" FontSize="26.667" Visibility="Collapsed"/>
<TextBox x:Name="AddMake" Grid.Column="1" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="425" FontSize="26.667" Visibility="Collapsed"/>
<TextBox x:Name="AddModel" Grid.Column="2" TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Height="52" Grid.ColumnSpan="1" TextAlignment="Center" Width="366" FontSize="26.667" Visibility="Collapsed"/>
</Grid>
</UserControl>
That let's you do everything you need to do from a UserControl that can be instantiated, has it's own code behind, etc. You can get that working exactly how you want, and then reference it when you need it in your list like this:
<ListView x:Name="VehicleList" HorizontalAlignment="Center" Height="120" Margin="0" VerticalAlignment="Center" Width="1119" Background="{ThemeResource CheckBoxDisabledForegroundThemeBrush}" SelectionChanged="VehicleList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<myProject:VehicleListItem/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The ListView will assign a vehicle item to the DataContext of your user control and everything will work just like you designed it to.
There is a way to get at the visual tree in code behind but it is very convoluted. Essentially you need to use the ListView.ItemContainerGenerator and call ContainerFromItem(dataItem) (ref) and then walk down the visual tree you get from that. It's not only a serious pain to do, there's no guarantee all of the API will be accessible from WPF to UWP or SilverLight. The cleanest solution is to break up the code into independent pieces.
Another solution, which probably is even more clean that what I proposed is to take advantage of your bound objects. ListView.SelectedItem returns your object that is bound to the DataTemplate. Just get the values from that object. If you have a ViewModel that includes properties for AddYear, AddMake, and AddModel then it makes a lot of the work easier to do since you aren't dealing with XAML at all.
If it's okay for you to do this on a button-click; you could use the CommandParameter or traverse the VisualTree like these two links suggest:
How to get text from TextBox inside ListViewItem's DataTemplate
How to get the value out of a textbox in XAML?
UserControl
It sounds like a UserControl is what you are looking for.
Project → Add UserControl
It should be easy since you already have the XAML design. The code behind will look something like this:
public class VehicleView : UserControl
{
// Year
public static readonly DependencyProperty YearProperty =
DependencyProperty.Register("Year", typeof(int), typeof(VehicleView),
new PropertyMetadata());
public int Year
{
get { return (int)GetValue(YearProperty); }
set { SetValue(YearProperty, value); }
}
// Make
public static readonly DependencyProperty MakeProperty =
DependencyProperty.Register("Make", typeof(string), typeof(VehicleView),
new PropertyMetadata("None"));
public string Make
{
get { return (string)GetValue(MakeProperty); }
set { SetValue(MakeProperty, value); }
}
// Model
public static readonly DependencyProperty ModelProperty =
DependencyProperty.Register("Model", typeof(string), typeof(VehicleView),
new PropertyMetadata("None"));
public string Model
{
get { return (string)GetValue(ModelProperty); }
set { SetValue(ModelProperty, value); }
}
public VehicleView()
{
InitializeComponent();
}
}
Binding words the same way. Just name the UserControl with x:Name. Something like:
<UserControl x:Name="vehicleview"
x:Class="MyProjectClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid>
<!-- Here's where your ListView goes. -->
<TextBox Text="{Binding ElementName=vehicleview, Path=Model}"/>
<Grid>
</UserControl>
As i can see you have used bindings.
On VehicleList_SelectionChanged you can do the following
List<YouClass-Model> selectedItems = VehicleList.SelectedItems.Cast<YouClass-Model>().ToList();
or if you use ItemClicked EventHandler
YouClass-Model itemClicked = (YouClass-Model)e.ClickedItem)
That way you can load the binded data. ex itemClicked.Model
Also make sure that you binded your data correctly
Data binding overview
INotifyPropertyChanged.PropertyChanged
To get the UI control from the index or data, use listView.ContainerFromIndex or listView.ContainerFromItem. This is the accepted way in UWP.
try this code:
private void myListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
ListItemData data = args.Item as ListItemData;
ListViewItem a = args.ItemContainer as ListViewItem;
var b = a.ContentTemplateRoot as Grid;
var txtBlock =b.FindName("txtTitle") as TextBlock;
txtBlock.Text = data.Title;
TextRange textRange = new TextRange()
{
StartIndex = 1,
Length = 3
};
TextHighlighter highlighter = new TextHighlighter()
{
Background = new SolidColorBrush(Colors.Yellow),
Ranges = { textRange }
};
txtBlock.TextHighlighters.Add(highlighter);
}

Custom ListView from inside HubAppSection -- Windows Phone 8.1

I am currently building a Windows Phone Applicaation, based off of the HubAppTemplate.
The template comes with a sample .JSON data source that it uses to populate the data of each HubSection. However, I want to use a non JSON type of data as the basis of my code. Inside my C# code, I need to make a function call to my backend to get the type of data I want out of it.
I can put this data inside of my own custom list (on the C# side), but how can I make that list act as the data source for my HubSection? Any old listview/list box works perfectly. Basically, I need help wiring the C# to the XAML -- the main issue is that I cannot access my listView inside of the datatemplate by name.
Can anyone give me some pointers to get going in the right direction?
Here is some reference code to show you what I am talking about:
<HubSection x:Uid="Clubs" Header="Clubs" DataContext="{Binding Groups}" HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}">
<DataTemplate>
<ListView Name="ClubsList"
IsItemClickEnabled="True"
ItemsSource="{Binding}"
ItemClick="GroupSection_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,27.5">
<TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</HubSection>
The above XAML is basically pulled straight from the hubapp template. I want to be able to use my own itemssource inside of that ListView that is generated from my C# code -- however, I cannot figure out how this ItemsSource works. I also cannot access my listview by name (ClubsList).
Here is the initialization code going on up top (wasn't sure if it was important to post this or not):
<Page
x:Class="HubAppTemplate.HubPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HubAppTemplate"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:HubAppTemplate.Data"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
d:DataContext="{Binding Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="HubSectionHeaderTemplate">
<TextBlock Margin="0,0,0,-9.5" Text="{Binding}"/>
</DataTemplate>
<!-- Grid-appropriate item template as seen in section 2 -->
<DataTemplate x:Key="Standard200x180TileItemTemplate">
<Grid Margin="0,0,9.5,9.5" Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" Height="138.5" Width="138.5"/>
<TextBlock Text="{Binding Title}" VerticalAlignment="Bottom" Margin="9.5,0,0,6.5" Style="{ThemeResource BaseTextBlockStyle}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="StandardTripleLineItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0" Grid.Column="0" HorizontalAlignment="Left">
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" Height="79" Width="79"/>
</Border>
<StackPanel Grid.Column="1" Margin="14.5,0,0,0">
<TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="{Binding Description}" Style="{ThemeResource ListViewItemContentTextBlockStyle}" Foreground="{ThemeResource PhoneMidBrush}" />
<TextBlock Text="{Binding Subtitle}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="StandardDoubleLineItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0" Grid.Column="0" HorizontalAlignment="Left">
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" Height="79" Width="79"/>
</Border>
<StackPanel Grid.Column="1" Margin="14.5,0,0,0">
<TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="{Binding Subtitle}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>
</StackPanel>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid x:Name="LayoutRoot">
<Hub x:Name="Hub" x:Uid="Hub" Header="Club Alert" Background="{ThemeResource HubBackgroundImageBrush}">
It is pulling from the JSON backend, but I want to just use my own custom listview for each section. Deleting the DataSource and data template headers gives me errors, however.
Thank you so much for your help in advance!
--A total newbie
HubSection elements require their contents to be populated via a template, so you can't just remove the <DataTemplate> tags, unfortunately. However, there is a simple way to accomplish what you are trying to do, if I understand you correctly.
If you're starting with the default Hub template, you should have this function in your HubPage.xaml.cs file
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var sampleDataGroups = await SampleDataSource.GetGroupsAsync();
this.DefaultViewModel["Groups"] = sampleDataGroups;
MainViewModel viewModel = DataContext as MainViewModel;
if (!viewModel.IsDataLoaded)
{
viewModel.Load();
}
}
this.DefaultViewModel is just a Dictionary, and they have loaded the sample JSON into a variable and stored this in the ["Groups"] key of the dictionary. Since the Page's DataContext is being bound to {Binding DefaultViewModel, RelativeSource={RelativeSource Self}}, the HubSection's DataContext is being bound to {Binding Groups}, and the ItemsSource of the ListView in each DataTemplate is being bound to {Binding}, each element of the loaded JSON is being used to fill the items of the ListView.
A simple solution would be to assign this.DefaultViewModel["Groups"] to the C# List you are creating from the data you load from your back end.
Something like this:
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var myData = await GetListOfThingsFromBackend();
this.DefaultViewModel["Groups"] = myData;
MainViewModel viewModel = DataContext as MainViewModel;
if (!viewModel.IsDataLoaded)
{
viewModel.Load();
}
}
A better approach would probably be to separate out all ViewModel functionality to it's own class that is better suited to your needs, and then adjust the various DataContext properties throughout the XAML, but that would likely take more time. I can elaborate if needed, but the simple solution is probably enough for now.

c# find texbox in WinPhone7 silverlight app

I have something like this:
<ListBox Height="456" Margin="30,113,0,0" x:Name="listBox1" Width="446" Background="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28" Orientation="Horizontal">
<TextBlock Text="{Binding name}" FontSize="28" Padding="10" >
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener
Hold="GestureListenerHold" />
</toolkit:GestureService.GestureListener>
</TextBlock>
<TextBlock Text="{Binding id}" FontSize="24" Padding="10" >
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener
Hold="GestureListenerHold" />
</toolkit:GestureService.GestureListener>
</TextBlock>
<TextBlock Text="{Binding status}" FontSize="24" Padding="10">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener
Hold="GestureListenerHold" />
</toolkit:GestureService.GestureListener>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and in my app i do:
data = (List<Device>)serializer.Deserialize(stream);
this.listBox1.ItemsSource = data;
on every textblock I have a gesture listener which should provide the user with the option to change 'name', so when they hold the textblock the app navigates him to another page where he fills in the form.
My question is how to find the texblock which is binding 'name' when I click and hold another texblock?
You could use Linq-to-VisualTree, a utility which I wrote which allows you to navigate the visual tree:
http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/
Firstly, name the TextBlock so that it can be uniquely identified:
<TextBlock x:Name="NameText" Text="{Binding name}" FontSize="28" Padding="10" />
Then, when one of your other TextBlocks is tapped, you can find it as follows:
// locate the parent stackpanel
var parentStackPanel = tappedTextBlock.Ancestors().First()
// locate the names TextBlock
var nameTextBlock = parentStackPanel.Elements()
.Where(el => el.Name == "NameText").Single();
Cast the sender in the GestureListenerHold method.

How to change datatemplate through code

I have ListBox and DataTemplate
I need Set GroupBox Heigth = 300
How to do it?
<DataTemplate x:Key="data_template">
<GroupBox Header="Категория" Width="300" HorizontalAlignment="Stretch" x:Name="GroupBox">
<DockPanel Tag="{Binding id}">
<Button Click="Button_Click" DockPanel.Dock="Top" >
<Button.Content>
<DockPanel>
<TextBlock Text="{Binding title}" TextWrapping="Wrap" DockPanel.Dock="Top" Padding="5" HorizontalAlignment="Center" Foreground="#FFB51414" />
<l:ScrollViewerEx VerticalScrollBarVisibility="Auto" >
<TextBlock Text="{Binding description}" DockPanel.Dock="Top" TextWrapping="Wrap" Padding="5" IsHitTestVisible="False" />
</l:ScrollViewerEx>
</DockPanel>
</Button.Content>
</Button>
</DockPanel>
</GroupBox>
</DataTemplate>
In case, someone tried to resolve my previous question, I did it like the following:
DataTemplate mycolumnDataTemplate = null;
var dataTemplateStream = new SomeClass().GetType().Assembly.GetManifestResourceStream("Some.Namespace.SomeReosurceName.xaml");
string dataTemplateString = new System.IO.StreamReader(dataTemplateStream).ReadToEnd();
dataTemplateString = dataTemplateString.Replace("[0]", browserColumn.ColumnName);
mycolumnDataTemplate = XamlReader.Load(dataTemplateString) as DataTemplate;
What are you trying to achieve? Do you want the GroupBox Height to be changed at the runtime of your application, when some event occurred or some data has changed? If so, then what you are probably looking for is a data trigger or event trigger, which you simply need to add to your DataTemplate.

Categories

Resources