- darthmaule2
- Posts: 98
- Joined:
How to use DataTemplateSelector?
I'm trying to port from a WPF application that is using a DataTemplateSelector.
The XAML is defining DataTemplate resources, a DataTemplateSelector, and assigning DataTemplates to the selector's properties.
I have created a class to implement my DataTemplateSelector
While defining my DataTemplate properties,
I followed the pattern I had used elsewhere for defining a property of type NsBool, but this is not working.
When I compile I get:
error C2248: 'Noesis::Gui::FrameworkTemplate::operator =' : cannot access private member declared in class 'Noesis::Gui::FrameworkTemplate'
Thinking that this error was caused by the assignments done in the Setters, I commented out the assignments.
Then I get:
error C2248: 'Noesis::Core::BaseComponent::BaseComponent' : cannot access private member declared in class 'Noesis::Core::BaseComponent'
This diagnostic occurred in the compiler generated function 'Noesis::Gui::FrameworkTemplate::FrameworkTemplate(const Noesis::Gui::FrameworkTemplate &)'
Should I be attempting to define properties of type DataTemplate?
Is it possible to set their values in the xaml as I am attempting to do?
How would this be accomplished?
The XAML is defining DataTemplate resources, a DataTemplateSelector, and assigning DataTemplates to the selector's properties.
Code: Select all
<DataTemplate x:Key="TextDataTemplate">
<TextBlock TextWrapping="NoWrap" Text="{Binding StatusItemText}" Margin="5,0,0,0" Focusable="False" FontFamily="#/Fonts/Arial" FontSize="16" Foreground="#EBEBEB"/>
</DataTemplate>
<DataTemplate x:Key="IconDataTemplate">
<Grid Height="24" Width="24" Margin="5,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Focusable="False">
<ContentControl Content="{Binding StatusItemIconPath}" Focusable="False"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="BigIconDataTemplate">
<Grid Height="32" Width="32" Margin="5,0,5,0" HorizontalAlignment="Center" VerticalAlignment="Center" Focusable="False">
<ContentControl Content="{Binding StatusItemIconPath}" Focusable="False"/>
</Grid>
</DataTemplate>
<local:StatusItemTemplateSelector x:Key="statusItemTemplateSelector"
TextDataTemplate="{StaticResource TextDataTemplate}"
IconDataTemplate="{StaticResource IconDataTemplate}"
BigIconDataTemplate="{StaticResource BigIconDataTemplate}"/>
Code: Select all
NS_DECLARE_SYMBOL(TextDataTemplate)
NS_DECLARE_SYMBOL(IconDataTemplate)
NS_DECLARE_SYMBOL(BigIconDataTemplate)
class StatusItemTemplateSelector : public DataTemplateSelector
{
public:
StatusItemTemplateSelector() {}
~StatusItemTemplateSelector() {}
DataTemplate* SelectTemplate(Core::BaseComponent* item, DependencyObject* container)
{
StatusBar_Item* statusItem = NsStaticCast<StatusBar_Item*>(item);
if (statusItem == nullptr)
return &_textDataTemplate;
NsString idString = statusItem->GetStatusItemID();
if (idString == "A")
return &_iconDataTemplate;
else if (idString == "B")
return &_bigIconDataTemplate;
else
return &_textDataTemplate;
}
DataTemplate GetTextDataTemplate() const
{
return _textDataTemplate;
}
void SetTextDataTemplate(const DataTemplate pTemplate)
{
_textDataTemplate = pTemplate;
}
DataTemplate GetIconDataTemplate() const
{
return _iconDataTemplate;
}
void SetIconDataTemplate(const DataTemplate pTemplate)
{
_iconDataTemplate = pTemplate;
}
DataTemplate GetBigIconDataTemplate() const
{
return _bigIconDataTemplate;
}
void SetBigIconDataTemplate(const DataTemplate pTemplate)
{
_bigIconDataTemplate = pTemplate;
}
private:
DataTemplate _textDataTemplate;
DataTemplate _iconDataTemplate;
DataTemplate _bigIconDataTemplate;
NS_IMPLEMENT_INLINE_REFLECTION(StatusItemTemplateSelector, DataTemplateSelector)
{
NsMeta<TypeId>("StatusItemTemplateSelector");
NsProp("TextDataTemplate", &StatusItemTemplateSelector::GetTextDataTemplate, &StatusItemTemplateSelector::SetTextDataTemplate);
NsProp("IconDataTemplate", &StatusItemTemplateSelector::GetIconDataTemplate, &StatusItemTemplateSelector::SetIconDataTemplate);
NsProp("BigIconDataTemplate", &StatusItemTemplateSelector::GetBigIconDataTemplate, &StatusItemTemplateSelector::SetBigIconDataTemplate);
}
};
I followed the pattern I had used elsewhere for defining a property of type NsBool, but this is not working.
When I compile I get:
error C2248: 'Noesis::Gui::FrameworkTemplate::operator =' : cannot access private member declared in class 'Noesis::Gui::FrameworkTemplate'
Thinking that this error was caused by the assignments done in the Setters, I commented out the assignments.
Then I get:
error C2248: 'Noesis::Core::BaseComponent::BaseComponent' : cannot access private member declared in class 'Noesis::Core::BaseComponent'
This diagnostic occurred in the compiler generated function 'Noesis::Gui::FrameworkTemplate::FrameworkTemplate(const Noesis::Gui::FrameworkTemplate &)'
Should I be attempting to define properties of type DataTemplate?
Is it possible to set their values in the xaml as I am attempting to do?
How would this be accomplished?
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: How to use DataTemplateSelector?
Hi,
DataTemplate is a ref counted object, so you have to work with pointers and Ptr:
DataTemplate is a ref counted object, so you have to work with pointers and Ptr:
Code: Select all
class StatusItemTemplateSelector : public DataTemplateSelector
{
public:
StatusItemTemplateSelector() {}
~StatusItemTemplateSelector() {}
DataTemplate* SelectTemplate(Core::BaseComponent* item, DependencyObject* container)
{
StatusBar_Item* statusItem = NsStaticCast<StatusBar_Item*>(item);
if (statusItem == nullptr)
return _textDataTemplate.GetPtr();
NsString idString = statusItem->GetStatusItemID();
if (idString == "A")
return _iconDataTemplate.GetPtr();
else if (idString == "B")
return _bigIconDataTemplate.GetPtr();
else
return _textDataTemplate.GetPtr();
}
DataTemplate* GetTextDataTemplate() const
{
return _textDataTemplate.GetPtr();
}
void SetTextDataTemplate(DataTemplate* pTemplate)
{
_textDataTemplate.Reset(pTemplate);
}
DataTemplate* GetIconDataTemplate() const
{
return _iconDataTemplate.GetPtr();
}
void SetIconDataTemplate(DataTemplate* pTemplate)
{
_iconDataTemplate.Reset(pTemplate);
}
DataTemplate* GetBigIconDataTemplate() const
{
return _bigIconDataTemplate.GetPtr();
}
void SetBigIconDataTemplate(DataTemplate* pTemplate)
{
_bigIconDataTemplate.Reset(pTemplate);
}
private:
Ptr<DataTemplate> _textDataTemplate;
Ptr<DataTemplate> _iconDataTemplate;
Ptr<DataTemplate> _bigIconDataTemplate;
NS_IMPLEMENT_INLINE_REFLECTION(StatusItemTemplateSelector, DataTemplateSelector)
{
NsMeta<TypeId>("StatusItemTemplateSelector");
NsProp("TextDataTemplate", &StatusItemTemplateSelector::GetTextDataTemplate, &StatusItemTemplateSelector::SetTextDataTemplate);
NsProp("IconDataTemplate", &StatusItemTemplateSelector::GetIconDataTemplate, &StatusItemTemplateSelector::SetIconDataTemplate);
NsProp("BigIconDataTemplate", &StatusItemTemplateSelector::GetBigIconDataTemplate, &StatusItemTemplateSelector::SetBigIconDataTemplate);
}
};
- darthmaule2
- Posts: 98
- Joined:
Re: How to use DataTemplateSelector?
Thank you -- after switching to pointers and Ptr, my c++ class is compiling without error :)
Unfortunately, I'm getting an error building the xaml resource.
I tried renaming the DataTemplate resources so they did not match the selector's properties, but that did not help.
If I comment out the setting of the DataTemplateSelector's properties, the xaml builds.
To verify the DataTemplate, I used TextDataTemplate_key elsewhere in the xaml file, and it not only builds, but works just fine at run time too.
But when I try to set any property, it fails
Unhandled exception at 0x0F5AC76D: Access Violation reading location 0x00000000
[ 0] [0x0F5AC76D] Noesis.dll!Noesis::Gui::StaticResourceExpression::Evaluate + 0x6d bytes
[ 1] [0x0F661BE7] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x3e97 bytes
[ 2] [0x0F66061B] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x28cb bytes
[ 3] [0x0F65D791] Noesis.dll!Noesis::Gui::NoesisApplication::Tick + 0x6211 bytes
[ 4] [0x0F65DAA6] Noesis.dll!Noesis::Gui::NoesisApplication::Tick + 0x6526 bytes
[ 5] [0x0F65F069] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x1319 bytes
[ 6] [0x0F65F28C] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x153c bytes
[ 7] [0x0F65F04F] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x12ff bytes
[ 8] [0x0F65F28C] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x153c bytes
[ 9] [0x0F65F04F] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x12ff bytes
[10] [0x0F6627EF] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x4a9f bytes
[11] [0x0F65F4C3] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x1773 bytes
[12] [0x0F381149] Noesis.dll!Noesis::Resource::Import + 0x539 bytes
[13] [0x0F38193A] Noesis.dll!Noesis::Resource::BaseImporter::OutputName + 0x65a bytes
[14] [0x0F380E5E] Noesis.dll!Noesis::Resource::Import + 0x24e bytes
[15] [0x00801756] Resource.BuildTool.exe
What is the correct way to initialize the DataTemplateSelector with the DataTemplate resources?
Unfortunately, I'm getting an error building the xaml resource.
I tried renaming the DataTemplate resources so they did not match the selector's properties, but that did not help.
If I comment out the setting of the DataTemplateSelector's properties, the xaml builds.
Code: Select all
<StatusItemTemplateSelector x:Key="statusItemTemplateSelector"
/>
<!--
TextDataTemplate="{StaticResource TextDataTemplate_key}"
IconDataTemplate="{StaticResource IconDataTemplate_key}"
BigIconDataTemplate="{StaticResource BigIconDataTemplate_key}"
-->
But when I try to set any property, it fails
Code: Select all
<StatusItemTemplateSelector x:Key="statusItemTemplateSelector"
TextDataTemplate="{StaticResource TextDataTemplate_key}"
/>
<!--
IconDataTemplate="{StaticResource IconDataTemplate_key}"
BigIconDataTemplate="{StaticResource BigIconDataTemplate_key}"
-->
[ 0] [0x0F5AC76D] Noesis.dll!Noesis::Gui::StaticResourceExpression::Evaluate + 0x6d bytes
[ 1] [0x0F661BE7] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x3e97 bytes
[ 2] [0x0F66061B] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x28cb bytes
[ 3] [0x0F65D791] Noesis.dll!Noesis::Gui::NoesisApplication::Tick + 0x6211 bytes
[ 4] [0x0F65DAA6] Noesis.dll!Noesis::Gui::NoesisApplication::Tick + 0x6526 bytes
[ 5] [0x0F65F069] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x1319 bytes
[ 6] [0x0F65F28C] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x153c bytes
[ 7] [0x0F65F04F] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x12ff bytes
[ 8] [0x0F65F28C] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x153c bytes
[ 9] [0x0F65F04F] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x12ff bytes
[10] [0x0F6627EF] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x4a9f bytes
[11] [0x0F65F4C3] Noesis.dll!Noesis::Gui::ItemCollection::CollectionChanged + 0x1773 bytes
[12] [0x0F381149] Noesis.dll!Noesis::Resource::Import + 0x539 bytes
[13] [0x0F38193A] Noesis.dll!Noesis::Resource::BaseImporter::OutputName + 0x65a bytes
[14] [0x0F380E5E] Noesis.dll!Noesis::Resource::Import + 0x24e bytes
[15] [0x00801756] Resource.BuildTool.exe
What is the correct way to initialize the DataTemplateSelector with the DataTemplate resources?
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: How to use DataTemplateSelector?
I need to set up a sample with this scenario to reproduce the crash, it seems a bug in our side.
Please create a ticket in our bugtracker and I will take a look as soon as possible.
Thanks.
Please create a ticket in our bugtracker and I will take a look as soon as possible.
Thanks.
- darthmaule2
- Posts: 98
- Joined:
Re: How to use DataTemplateSelector?
When I select Bugtracking tab, I am prompted to log in.
I'm trying the same ID & password I've logged in with now, but it does not work for Bugtracking
I'm trying the same ID & password I've logged in with now, but it does not work for Bugtracking
Re: How to use DataTemplateSelector?
Signup for a new account.When I select Bugtracking tab, I am prompted to log in.
I'm trying the same ID & password I've logged in with now, but it does not work for Bugtracking
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: How to use DataTemplateSelector?
Forum and bugtracker have different user database, and require you register in both.When I select Bugtracking tab, I am prompted to log in.
I'm trying the same ID & password I've logged in with now, but it does not work for Bugtracking
About the issue exposed in this topic I fixed it for the next release.
- darthmaule2
- Posts: 98
- Joined:
Re: How to use DataTemplateSelector?
When do you expect to release 1.2.1?
Re: How to use DataTemplateSelector?
This issue is already fixed. If you need it please ask for a hotfix in the corresponding ticket. We could generate you a version.
Thanks!
Thanks!
- darthmaule2
- Posts: 98
- Joined:
Re: How to use DataTemplateSelector?
Thank you for the quick fix. Using v1.2.1 my DataTemplateSelector initialization builds without error.
Unfortunately, it's not working right at run time -- I'm probably still doing something wrong.
I've been simplifying my xaml and code behind to reduce the potential errors, but I still cannot get it to work.
Instead of initializing my template selector properties with all of the various DataTemplates, I'm just setting all of the properties to a single DataTemplate that I have tested previously.
My current xaml UserControl.Resources contains just 1 DataTemplate and the selector, which is initialized using only that DataTemplate:
I know my DataTemplate is working because when I use it (without the selector) in the following xaml, then at run time my StatusBar_Item's text and icon name are displayed.
But it does not work, if I replace
ItemTemplate = "{StaticResource IconTextDataTemplate_key}"
with
ItemTemplateSelector="{DynamicResource statusItemTemplateSelector}"
Using the selector, at run time, I just get "StatusBar_Item" displayed. I believe this means no template was found, so the item's ToString() was called instead.
I've even simplified my DataTemplateSelector's SelectTemplate() method to reduce the potential for errors. Instead of actually looking at the StatusBar_Item's ID property to select a DataTemplate, it is just returning the same one all the time.
Can you see what I'm doing wrong here?
Unfortunately, it's not working right at run time -- I'm probably still doing something wrong.
I've been simplifying my xaml and code behind to reduce the potential errors, but I still cannot get it to work.
Instead of initializing my template selector properties with all of the various DataTemplates, I'm just setting all of the properties to a single DataTemplate that I have tested previously.
My current xaml UserControl.Resources contains just 1 DataTemplate and the selector, which is initialized using only that DataTemplate:
Code: Select all
<DataTemplate x:Key="IconTextDataTemplate_key">
<Grid Margin="2,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Focusable="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextWrapping="NoWrap" Text="{Binding StatusItemIconPath}" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Center"
Focusable="False" FontFamily="#/Fonts/Arial" FontSize="16" Foreground="#EBEBEB"/>
<TextBlock Grid.Column="1" TextWrapping="NoWrap" Text="{Binding StatusItemText}" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Center"
Focusable="False" FontFamily="#/Fonts/Arial" FontSize="16" Foreground="#EBEBEB"/>
</Grid>
</DataTemplate>
<StatusItemTemplateSelector x:Key="statusItemTemplateSelector"
TextDataTemplate="{StaticResource IconTextDataTemplate_key}"
IconDataTemplate="{StaticResource IconTextDataTemplate_key}"
BigIconDataTemplate="{StaticResource IconTextDataTemplate_key}"
IconTextDataTemplate="{StaticResource IconTextDataTemplate_key}"
/>
Code: Select all
<ItemsControl x:Name="System_StatusBarArea" Grid.Column="1" Grid.Row="0"
HorizontalAlignment="Right"
Background="Transparent"
BorderThickness="0" BorderBrush="{x:Null}"
Focusable="False"
DataContext="{StaticResource systemStatusDataModel}"
ItemTemplate = "{StaticResource IconTextDataTemplate_key}"
ItemsSource="{Binding StatusBarItemList}"
Visibility="{Binding StatusBarItemListVisibility}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
ItemTemplate = "{StaticResource IconTextDataTemplate_key}"
with
ItemTemplateSelector="{DynamicResource statusItemTemplateSelector}"
Using the selector, at run time, I just get "StatusBar_Item" displayed. I believe this means no template was found, so the item's ToString() was called instead.
I've even simplified my DataTemplateSelector's SelectTemplate() method to reduce the potential for errors. Instead of actually looking at the StatusBar_Item's ID property to select a DataTemplate, it is just returning the same one all the time.
Code: Select all
NS_DECLARE_SYMBOL(TextDataTemplate)
NS_DECLARE_SYMBOL(IconDataTemplate)
NS_DECLARE_SYMBOL(BigIconDataTemplate)
NS_DECLARE_SYMBOL(IconTextDataTemplate)
class StatusItemTemplateSelector : public DataTemplateSelector
{
public:
StatusItemTemplateSelector() {}
~StatusItemTemplateSelector() {}
DataTemplate* SelectTemplate(Core::BaseComponent* item, DependencyObject* container)
{
return _iconTextDataTemplate.GetPtr();
}
DataTemplate* GetTextDataTemplate() const
{
return _textDataTemplate.GetPtr();
}
void SetTextDataTemplate(DataTemplate* pTemplate)
{
_textDataTemplate.Reset(pTemplate);
}
DataTemplate* GetIconDataTemplate() const
{
return _iconDataTemplate.GetPtr();
}
void SetIconDataTemplate(DataTemplate* pTemplate)
{
_iconDataTemplate.Reset(pTemplate);
}
DataTemplate* GetBigIconDataTemplate() const
{
return _bigIconDataTemplate.GetPtr();
}
void SetBigIconDataTemplate(DataTemplate* pTemplate)
{
_bigIconDataTemplate.Reset(pTemplate);
}
DataTemplate* GetIconTextDataTemplate() const
{
return _iconTextDataTemplate.GetPtr();
}
void SetIconTextDataTemplate(DataTemplate* pTemplate)
{
_iconTextDataTemplate.Reset(pTemplate);
}
private:
Ptr<DataTemplate> _textDataTemplate;
Ptr<DataTemplate> _iconDataTemplate;
Ptr<DataTemplate> _bigIconDataTemplate;
Ptr<DataTemplate> _iconTextDataTemplate;
NS_IMPLEMENT_INLINE_REFLECTION(StatusItemTemplateSelector, DataTemplateSelector)
{
NsMeta<TypeId>("StatusItemTemplateSelector");
NsProp("TextDataTemplate", &StatusItemTemplateSelector::GetTextDataTemplate, &StatusItemTemplateSelector::SetTextDataTemplate);
NsProp("IconDataTemplate", &StatusItemTemplateSelector::GetIconDataTemplate, &StatusItemTemplateSelector::SetIconDataTemplate);
NsProp("BigIconDataTemplate", &StatusItemTemplateSelector::GetBigIconDataTemplate, &StatusItemTemplateSelector::SetBigIconDataTemplate);
NsProp("IconTextDataTemplate", &StatusItemTemplateSelector::GetIconTextDataTemplate, &StatusItemTemplateSelector::SetIconTextDataTemplate);
}
};
Can you see what I'm doing wrong here?
Who is online
Users browsing this forum: Ahrefs [Bot], Semrush [Bot] and 2 guests