Page 2 of 2

Re: How to use DataTemplateSelector?

Posted: 27 Mar 2015, 21:29
by sfernandez
Hi,

I was able to run your sample (a bit more simplified) in the XamlPlayer:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="TestPanel">
    <Grid.Resources>
        <DataTemplate x:Key="IconTextDataTemplate_key">
            <Grid HorizontalAlignment="Center" Margin="2,0,0,0" VerticalAlignment="Center">
                <TextBlock
                    HorizontalAlignment="Center"
                    Margin="0"
                    VerticalAlignment="Center"
                    Focusable="False"
                    FontSize="16"
                    Foreground="Black"
                    Text="{Binding StatusItemText}"
                    TextWrapping="NoWrap"/>
            </Grid>
        </DataTemplate>
        <StatusItemTemplateSelector x:Key="statusItemTemplateSelector"
            IconTextDataTemplate="{StaticResource IconTextDataTemplate_key}"/>
    </Grid.Resources>
    <ItemsControl x:Name="System_StatusBarArea"
        Width="200" Height="100"
        Background="Silver" BorderBrush="Gray" BorderThickness="4"
        ItemTemplateSelector="{StaticResource statusItemTemplateSelector}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid> 
struct StatusBar_Item : public BaseComponent
{
    StatusBar_Item(const NsChar* itemText) : mItemText(itemText) {}

    const NsChar* GetStatusItemText() const { return mItemText.c_str(); }

    NsString mItemText;

    NS_IMPLEMENT_INLINE_REFLECTION(StatusBar_Item, BaseComponent)
    {
        NsMeta<TypeId>("StatusBar_Item");
        NsProp("StatusItemText", &StatusBar_Item::GetStatusItemText);
    }
}; 
struct StatusItemTemplateSelector : public DataTemplateSelector
{
    StatusItemTemplateSelector() {}
    ~StatusItemTemplateSelector() {}

    DataTemplate* SelectTemplate(Core::BaseComponent* item, DependencyObject* container)
    {
        return _iconTextDataTemplate.GetPtr();
    }

    DataTemplate* GetIconTextDataTemplate() const
    {
        return _iconTextDataTemplate.GetPtr();
    }
    void SetIconTextDataTemplate(DataTemplate* pTemplate)
    {
        _iconTextDataTemplate.Reset(pTemplate);
    }

    Ptr<DataTemplate> _iconTextDataTemplate;

    NS_IMPLEMENT_INLINE_REFLECTION(StatusItemTemplateSelector, DataTemplateSelector)
    {
        NsMeta<TypeId>("StatusItemTemplateSelector");
        NsProp("IconTextDataTemplate",
            &StatusItemTemplateSelector::GetIconTextDataTemplate,
            &StatusItemTemplateSelector::SetIconTextDataTemplate);
    }
}; 
struct TestPanel : Grid
{
    TestPanel() {}
    ~TestPanel() {}

    void OnPostInit()
    {
        ItemsControl* ic = FindName<ItemsControl>("System_StatusBarArea");
        Ptr<Collection> items = *new Collection();
        Ptr<StatusBar_Item> item;

        item = *new StatusBar_Item("Left");
        items->Add(item.GetPtr());

        item = *new StatusBar_Item("Center");
        items->Add(item.GetPtr());

        item = *new StatusBar_Item("Right");
        items->Add(item.GetPtr());

        ic->SetItemsSource(items.GetPtr());
    }

    NS_IMPLEMENT_INLINE_REFLECTION(TestPanel, Grid)
    {
        NsMeta<TypeId>("TestPanel");
    }
}; 
Please let me know if it works for you. Perhaps you can expand this sample until you get the whole sample working.

NOTE: To specify the font family the # sign must be placed between the path and the family name, like this:
FontFamily="Fonts/#Arial" 

Re: How to use DataTemplateSelector?

Posted: 30 Mar 2015, 17:52
by darthmaule2
Yes - simplified to this extent, it is working for me now.
THANK YOU!

Now I'll start adding complexity back in one step at a time...

Re: How to use DataTemplateSelector?

Posted: 31 Mar 2015, 22:11
by darthmaule2
NO, IT ACTUALLY DID NOT WORK!!!
Sorry, I was using this in 3 places, and it turned out that in the place where I thought it was working, I had actually switched to a hardcoded ItemTemplate as a work around.

With more investigation, I verified that the StatusItemTemplateSelector was being instantiated, and the SelectTemplate() method was being called, but was returning NULL.
Unfortunately, the SetTextDataTemplate() was never called, so the selector had nothing to return. :(

Once I realized this, I added a name to my DataTemplate
       <DataTemplate x:Name="George" x:Key="TextDataTemplate_key" .........
and I added the following near the top of OnPostInit():
StatusItemTemplateSelector * myTemplateSelector =
               NsStaticCast<StatusItemTemplateSelector *>(ic->GetItemTemplateSelector());
DataTemplate* myTemplate = FindName<DataTemplate>("George");
		if (myTemplateSelector && myTemplate)
		{
			myTemplateSelector->SetTextDataTemplate(myTemplate);
		}
Once SetTextDataTemplate() was actually called, then the template selector finally worked.

This seems to be a bug in the initialization of a DataTemplateSelector from xaml.

Re: How to use DataTemplateSelector?

Posted: 01 Apr 2015, 18:55
by sfernandez
As explained in the corresponding bugtracker ticket, this issue is fixed and will be available in the next 1.2.2 release.

We thank you for the valuable feedback ;)