darthmaule2
Topic Author
Posts: 94
Joined: 23 Oct 2014, 19:54

How to use DataTemplateSelector?

13 Mar 2015, 16:13

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.
<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}"/>
I have created a class to implement my DataTemplateSelector
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);
	}
};
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?
 
User avatar
sfernandez
Site Admin
Posts: 1935
Joined: 22 Dec 2011, 19:20

Re: How to use DataTemplateSelector?

13 Mar 2015, 16:58

Hi,

DataTemplate is a ref counted object, so you have to work with pointers and Ptr:
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
Topic Author
Posts: 94
Joined: 23 Oct 2014, 19:54

Re: How to use DataTemplateSelector?

13 Mar 2015, 19:42

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.
		<StatusItemTemplateSelector x:Key="statusItemTemplateSelector" 
			/>

		<!--
                                          TextDataTemplate="{StaticResource TextDataTemplate_key}" 
                                          IconDataTemplate="{StaticResource IconDataTemplate_key}"
                                          BigIconDataTemplate="{StaticResource BigIconDataTemplate_key}"
		-->
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
		<StatusItemTemplateSelector x:Key="statusItemTemplateSelector" 
                                          TextDataTemplate="{StaticResource TextDataTemplate_key}" 
			/>

		<!--
                                          IconDataTemplate="{StaticResource IconDataTemplate_key}"
                                          BigIconDataTemplate="{StaticResource BigIconDataTemplate_key}"
		-->
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?
 
User avatar
sfernandez
Site Admin
Posts: 1935
Joined: 22 Dec 2011, 19:20

Re: How to use DataTemplateSelector?

13 Mar 2015, 19:51

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.
 
darthmaule2
Topic Author
Posts: 94
Joined: 23 Oct 2014, 19:54

Re: How to use DataTemplateSelector?

13 Mar 2015, 22:04

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
 
movra
Posts: 70
Joined: 02 Apr 2014, 20:35

Re: How to use DataTemplateSelector?

14 Mar 2015, 00:10

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
Signup for a new account.
 
User avatar
sfernandez
Site Admin
Posts: 1935
Joined: 22 Dec 2011, 19:20

Re: How to use DataTemplateSelector?

17 Mar 2015, 15:32

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
Forum and bugtracker have different user database, and require you register in both.

About the issue exposed in this topic I fixed it for the next release.
 
darthmaule2
Topic Author
Posts: 94
Joined: 23 Oct 2014, 19:54

Re: How to use DataTemplateSelector?

18 Mar 2015, 22:09

When do you expect to release 1.2.1?
 
User avatar
jsantos
Site Admin
Posts: 2922
Joined: 20 Jan 2012, 17:18
Contact:

Re: How to use DataTemplateSelector?

19 Mar 2015, 09:04

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!
 
darthmaule2
Topic Author
Posts: 94
Joined: 23 Oct 2014, 19:54

Re: How to use DataTemplateSelector?

26 Mar 2015, 15:10

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:
        <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}"
			/>
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.
	<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>
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.
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: No registered users and 1 guest