Huskinu
Topic Author
Posts: 12
Joined: 15 Mar 2021, 05:40

ListView of CheckBox with content binding

08 May 2021, 08:24

Hi,

I am trying to create a ListView of checkbox items, with data binding to a data model created in c++, but unable to make the checkbox items display. Not sure if there is anything I missed?
I referenced the tutorial here.

The XAML code is as follows:
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
    x:Class="FCheckBoxLisControl"
    x:Name="CheckBoxListElement">
    <UserControl.Resources>
        <Style x:Key="CheckBoxListHeaderStyle" TargetType="GridViewColumnHeader">
            <Setter Property="Background" Value="Cyan"/>
            <Setter Property="Foreground" Value="Navy"/>
            <Setter Property="Visibility" Value="Collapsed"/>
        </Style>
        <DataTemplate x:Key="CheckBoxListHeaderTemplate" DataType="GridViewColumnHeader">
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>
        <DataTemplate x:Key="CheckBoxListCellTemplate">
            <CheckBox Margin="0,5,0,0"
                      Content="{Binding Name}"/>
        </DataTemplate>
        <DataTemplate x:Key="CheckBoxItemTemplate">
            <TextBlock Text="{Binding Name}">
                <TextBlock.ToolTip>
                    <ToolTip Visibility="Collapsed">
                        <TextBlock Text="{Binding Description}"/>
                    </ToolTip>
                </TextBlock.ToolTip>
            </TextBlock>
        </DataTemplate>
    </UserControl.Resources>
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <ListView x:Name="CheckBoxList"
                  SelectionMode="Multiple"
                  ItemsSource="{Binding ItemList}"
                  ItemTemplate="{StaticResource CheckBoxItemTemplate}">
            <ListView.View>
                <GridView>
                    <GridViewColumn HeaderTemplate="{StaticResource CheckBoxListHeaderTemplate}"
                                    HeaderContainerStyle="{StaticResource CheckBoxListHeaderStyle}"
                                    CellTemplate="{StaticResource CheckBoxListCellTemplate}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>
</UserControl>
C++ code:
NotifyPropertyChangedBase.h
at NoesisGUI/Source/Noesis/NoesisSDK/Src/Packages/App/ApplicationLauncher/Include/NsApp/NotifyPropertyChangedBase.h
NotifyPropertyChangedBase.cpp
at NoesisGUI/Source/Noesis/NoesisSDK/Src/Packages/App/ApplicationLauncher/Src/NotifyPropertyChangedBase.cpp

CustomDataModel.h
class FCustomDataItem : public Noesis::BaseComponent
{
public:
    FCustomDataItem(const char* InName, Noesis::ResourceDictionary* InDescription) : Name(InName), Description(InDescription)
    {
    }

    const char* GetName() const
    {
        return Name.Str();
    }

    Noesis::ResourceDictionary* GetDescription() const
    {
        return Description;
    }

private:
    Noesis::String Name;
    Noesis::Ptr<Noesis::ResourceDictionary> Description;

    NS_DECLARE_REFLECTION(FCustomDataItem, Noesis::BaseComponent)
};

class FCustomDataModel : public NotifyPropertyChangedBase
{
public:
    FCustomDataModel();

    Noesis::ObservableCollection<FCustomDataItem>* GetItemList() const
    {
        return ItemList.GetPtr();
    }

    void AddItem(Noesis::Ptr<FCustomDataItem> InItem)
    {
        ItemList->Add(InItem);
    }

    void RemoveItem(Noesis::Ptr<FCustomDataItem> InItem)
    {
        ItemList->Remove(InItem);
    }

    void Reset()
    {
        Noesis::DynamicCast<Noesis::BaseCollection*>(GetItemList())->Clear();
    }

    int Num() const
    {
        return ItemList->Count();
    }

    void SetCurrentItem(FCustomDataItem* InItem);
    FCustomDataItem* GetCurrentItem() const
    {
        return CurrentItem;
    }

    void SetCurrentIndex(uint32_t InItemIndex);

private:
    Noesis::Ptr<Noesis::ObservableCollection<FCustomDataItem>> ItemList;
    FCustomDataItem* CurrentItem = nullptr;

    NS_DECLARE_REFLECTION(FCustomDataModel, FNotifyPropertyChangedBase)
};
CustomDataModel.cpp
FCustomDataModel::FCustomDataModel()
{
    ItemList = Noesis::MakePtr<Noesis::ObservableCollection<FCustomDataItem>>();
    TArray<FString> itemContentList = { "A", "B" };
    for (const auto& itemContent : itemContentList)
    {
        ItemList->Add(Noesis::MakePtr<FCustomDataItem>(TCHAR_TO_UTF8(*itemContent), nullptr));
    }
    SetCurrentIndex(0);
}

void FCustomDataModel::SetCurrentItem(FCustomDataItem* InItem)
{
    if (CurrentItem != InItem)
    {
        CurrentItem = InItem;
        OnPropertyChanged("CurrentItem");
    }
}

void FCustomDataModel::SetCurrentIndex(uint32_t InItemIndex)
{
    SetCurrentItem(ItemList->Get(InItemIndex));
}

NS_BEGIN_COLD_REGION

NS_IMPLEMENT_REFLECTION(FCustomDataItem)
{
    NsProp("Name", &FCustomDataItem::GetName);
    NsProp("Description", &FCustomDataItem::GetDescription);
}

NS_IMPLEMENT_REFLECTION(FCustomDataModel)
{
    NsProp("ItemList", &FCustomDataModel::GetItemList);
    NsProp("CurrentItem", &FCustomDataModel::GetCurrentItem, &FCustomDataModel::SetCurrentItem);
}
CheckBoxListControl.h,.cpp
class FCheckBoxListControl : public Noesis::UserControl
{
public:
    FCheckBoxListControl()
    {
        XAMLDataModel = Noesis::MakePtr<FCustomDataModel>();
        Noesis::FrameworkElement::SetDataContext(XAMLDataModel);
    }

    Noesis::Ptr<FCustomDataModel> GetXAMLDataModel() const override final
    {
        return XAMLDataModel;
    }

protected:
    Noesis::Ptr<FCustomDataModel> XAMLDataModel = nullptr;

private:
    NS_DECLARE_REFLECTION(FCheckBoxListControl, Noesis::UserControl)
};

NS_BEGIN_COLD_REGION

NS_IMPLEMENT_REFLECTION(FCheckBoxListControl, "FCheckBoxListControl")
{
}
Any pointer is appreciated, thanks!
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: ListView of CheckBox with content binding

10 May 2021, 10:58

Are you including this FCheckBoxListControl as part of another xaml?

As described in the Unreal tutorial, you need to specify the xaml that should be loaded (LoadComponent) when constructing the user control, otherwise it will create a simple control with no content. And you should specify a namespace for the control name, so it can be correctly mapped in Blend and xaml. Finally you will need to register the component in your module so it can be created by the xaml parser.

I tried your code with the changes I mentioned and I was able to see the list with the check boxes. Could you confirm if that was your problem?

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 87 guests