-
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Programmatically Creating Elements from DataTemplate
Hi,
I need to generate multiple elements dynamically based on real time data and display them on some kind of host controller - WrapPannel in my example.
Each custom element has it's own name, id and display image which I load and create dynamically.
I created a a data template element and I want to fill the host container with multiple different instances.
1. What will be the best approach for this problem ?
2. How can I create a Frameworkelement based on this DataTemplate on runtime ?
3. How can I use the DataTemplate consept with ItemsControl ? I tried create a DataBinding to ItemsSource as well as adding items manually to the Items attribute but without success.
[EDIT]
I use the native SDK.
I need a quick sample that shows how to bind data to ItemsSource from independent application framework
One more related question to this -
When I create Gui resources dynamically such as TextBlocks, Buttons, etc I'm using the new keyword.
Should I use different allocation mechanism ? Who is in charge to free these elements ? The application code or Noesis SDK ?
I need to generate multiple elements dynamically based on real time data and display them on some kind of host controller - WrapPannel in my example.
Each custom element has it's own name, id and display image which I load and create dynamically.
I created a a data template element and I want to fill the host container with multiple different instances.
1. What will be the best approach for this problem ?
2. How can I create a Frameworkelement based on this DataTemplate on runtime ?
3. How can I use the DataTemplate consept with ItemsControl ? I tried create a DataBinding to ItemsSource as well as adding items manually to the Items attribute but without success.
[EDIT]
I use the native SDK.
I need a quick sample that shows how to bind data to ItemsSource from independent application framework
One more related question to this -
When I create Gui resources dynamically such as TextBlocks, Buttons, etc I'm using the new keyword.
Should I use different allocation mechanism ? Who is in charge to free these elements ? The application code or Noesis SDK ?
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Programmatically Creating Elements from DataTemplate
What you are trying to achieve is usually done with data binding.
You will have a data model (some class inheriting from BaseComponent) which exposes (via a reflection property) the list of dynamically created items (a Collection property). Each dynamically created item will be represented by a class (inheriting frpm BaseComponent) which exposes (via reflection) the properties you want to bind to your data template: name, id, image...
In your example it would be something like this:
The xaml that describes the DataTemplate and presents your items could be like this:
When the application starts, you can assign the Data Model instance in the DataContext property of the xaml root:
Take a look at Bindings native tutorial for more examples of data models and bindings.
You will have a data model (some class inheriting from BaseComponent) which exposes (via a reflection property) the list of dynamically created items (a Collection property). Each dynamically created item will be represented by a class (inheriting frpm BaseComponent) which exposes (via reflection) the properties you want to bind to your data template: name, id, image...
In your example it would be something like this:
Code: Select all
class DataModel: public BaseComponent
{
public:
DataModel(): _items(*new Collection()) { }
Collection* GetItems() const { return _items; }
private:
Ptr<Collection> _items;
NS_IMPLEMENT_INLINE_REFLECTION(DataModel, BaseComponent)
{
NsMeta<TypeId>("DataModel");
NsProp("Items", &DataModel::GetItems);
}
};
struct DataItem: public BaseComponent
{
DataItem(const NsChar* n, NsInt32 i, ImageSource* img):
_name(n), _id(i), _image(img)
{
}
NsString _name;
NsInt32 _id;
Ptr<ImageSource> _image;
NS_IMPLEMENT_INLINE_REFLECTION(DataItem, BaseComponent)
{
NsMeta<TypeId>("DataItem");
NsProp("Name", &DataModel::_name);
NsProp("Id", &DataModel::_id);
NsProp("Image", &DataModel::_image);
}
};
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="LayoutRoot">
<Grid.Resources>
<DataTemplate x:Key="MyItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}" Grid.Column="0" Margin="0,0,10,0"/>
<TextBlock Text="{Binding Name}" FontWeight="Bold" Grid.Column="1"/>
<TextBlock Text="{Binding Id}" TextAlignment="Right" Grid.Column="2"/>
</Grid>
</DataTemplate>
</Grid.Resources>
<ListBox Width="150" Height="100"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource MyItemTemplate}"/>
</Grid>
Code: Select all
Ptr<DataModel> data = *new DataModel();
Collection* items = data->GetItems();
// NsVector<Ptr<ImageSource> > images;
Ptr<DataItem> item1 = *new DataItem("Item1", 1, images[0].GetPtr());
items->Add(item1.GetPtr());
Ptr<DataItem> item2 = *new DataItem("Item2", 2, images[1].GetPtr());
items->Add(item2.GetPtr());
Ptr<DataItem> item3 = *new DataItem("Item3", 3, images[2].GetPtr());
items->Add(item3.GetPtr());
FrameworkElement* root = FindName<FrameworkElement>("LayoutRoot");
root->SetDataContext(data);
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Programmatically Creating Elements from DataTemplate
All BaseComponent inherited objects are reference counted. This references can be managed manually by AddReference()/Release() or you can use our smart pointer class: Ptr.Hi,
One more related question to this -
When I create Gui resources dynamically such as TextBlocks, Buttons, etc I'm using the new keyword.
Should I use different allocation mechanism ? Who is in charge to free these elements ? The application code or Noesis SDK ?
More information can be found in our documentation inside the SDK here:
- Doc/Core.Kernel.ComponentReferenceCounting.html
- Doc/Core.Kernel.ComponentSmartPointer.html
Re: Programmatically Creating Elements from DataTemplate
The recommended way is using smart pointers:
NOTE THE * BEFORE THE NEW OPERATOR
That way the button is removed whenever its last reference is destroyed. It is the easier way to avoid problems in C++ when using Dependency Objects.
By the way, the documents mentioned by sfernandez are not directly referenced by the index. We will fix this in the next version (1.1.3).
Code: Select all
Ptr<Button> sphere = *new Button();
That way the button is removed whenever its last reference is destroyed. It is the easier way to avoid problems in C++ when using Dependency Objects.
By the way, the documents mentioned by sfernandez are not directly referenced by the index. We will fix this in the next version (1.1.3).
-
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Re: Programmatically Creating Elements from DataTemplate
Thank you very much !
The Collection sample really helped me getting progressed with that.
I''ll keep in mind the recommandation of using smart pointers. For now I use raw data pointers and manage the Ref count myself..
The Collection sample really helped me getting progressed with that.
I''ll keep in mind the recommandation of using smart pointers. For now I use raw data pointers and manage the Ref count myself..
-
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Re: Programmatically Creating Elements from DataTemplate
I'm working on the DataModel example you suggested and I'm trying to extend it.
However it seems that there is some kind of cache file that holds the Binding attributes names.
I tried to rename the xaml Binding of the text block from Id to Desc as described below.
Original XAML Code:
Original Source Code:
Updated XAML Code:
Updated Source Code:
The updated version is not working. How can I solve it ?
However it seems that there is some kind of cache file that holds the Binding attributes names.
I tried to rename the xaml Binding of the text block from Id to Desc as described below.
Original XAML Code:
Code: Select all
<TextBlock Text="{Binding Id}" TextAlignment="Right" Grid.Column="2"/>
Code: Select all
NsProp("Id", &DataItem::m_strDesc);
Code: Select all
<TextBlock Text="{Binding Desc}" TextAlignment="Right" Grid.Column="2"/>
Code: Select all
NsProp("Desc", &DataItem::m_strDesc);
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Programmatically Creating Elements from DataTemplate
When a XAML file is builded to a UI resource (using our BuildTool.exe), the xml code is parsed and converted to Noesis objects. The only place I can think of keeping the old property name is in the UI resource, so my guess is you didn't rebuild your XAML file after modifying the code, otherwise we could be facing a bug here.
-
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Re: Programmatically Creating Elements from DataTemplate
I'm using a simple batch file for the UI Resources "compilation" process.
This batch file is doing the following:
1. Delete the entire package folder and subfolders of my application
under <SDK>\Data\Packages\[Package_Name].
2. Copy the package content and resources to the target package folder.
3. Run the BuildTool with the following options.
%BUILD_TOOL% scan --autoadd
%BUILD_TOOL% build
4. Copy back the generated binary cache files and updated guids file to my media folder.
I also tried deleting the entire generated binary folder under <SDK>\Bin\Data\DX9\[Package_Name].
None of these worked..
Do you have some other persistent storage that you use to store symbols in ? Maybe the registry of some other kind of data base in the user folder ?
This batch file is doing the following:
1. Delete the entire package folder and subfolders of my application
under <SDK>\Data\Packages\[Package_Name].
2. Copy the package content and resources to the target package folder.
3. Run the BuildTool with the following options.
%BUILD_TOOL% scan --autoadd
%BUILD_TOOL% build
4. Copy back the generated binary cache files and updated guids file to my media folder.
I also tried deleting the entire generated binary folder under <SDK>\Bin\Data\DX9\[Package_Name].
None of these worked..
Do you have some other persistent storage that you use to store symbols in ? Maybe the registry of some other kind of data base in the user folder ?
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Programmatically Creating Elements from DataTemplate
No other cache/registry stores XAML data apart from UI resources.
If you revert the NsProp name back to "Id" and the binding path in the xaml, does the TextBlock show the text again?
If you revert the NsProp name back to "Id" and the binding path in the xaml, does the TextBlock show the text again?
Re: Programmatically Creating Elements from DataTemplate
Note that this way you are rebuilding the entire data base each time. As you increase the number of xamls this can be quite inefficient. A simple "build" command is able to detect changes and start and incremental build.I'm using a simple batch file for the UI Resources "compilation" process.
This batch file is doing the following:
1. Delete the entire package folder and subfolders of my application
under <SDK>\Data\Packages\[Package_Name].
2. Copy the package content and resources to the target package folder.
3. Run the BuildTool with the following options.
%BUILD_TOOL% scan --autoadd
%BUILD_TOOL% build
4. Copy back the generated binary cache files and updated guids file to my media folder.
Who is online
Users browsing this forum: Ahrefs [Bot] and 10 guests