Page 1 of 1

Some limitations of ObservableCollection

Posted: 13 Sep 2017, 02:56
by nikobarli
It seems that there are several limitations of ObservableCollection as follows. Could you please confirm if they are really limitations (or it may be just me couldn't get it right)

1. ObservableCollection doesn't have Count property.

I couldn't bind to the property (e.g. "{Binding ItemList.Count}" failed).

And the documentation is also saying it doesn't have any property.
https://www.noesisengine.com/docs/Gui.C ... ction.html

2. Cannot use simple data structure (e.g. NsString, Drawing::Point) as its item type (types inherited BaseComponent are required).

Thanks.

Re: Some limitations of ObservableCollection

Posted: 13 Sep 2017, 13:14
by Wanderer
I am not very experienced, but this is working for me:
class DataModel :  public Noesis::UserControl // Noesis::Core::BaseComponent - this vas previous class, I change it to UserControl, maybe there is better solutions, but I don't know.
{
public:
	DataModel();
	// ... 
	static const Noesis::Gui::DependencyProperty * m_CountValue;
	NsInt32 m_GetCount() const;
	void m_SetCount();
private:
	Noesis::Ptr<Noesis::Gui::ObservableCollection<ContainerItem> > m_Container;
	Noesis::Ptr<ContainerItem> m_ContainerSelectedItem;
	NS_IMPLEMENT_INLINE_REFLECTION(DataModel, Noesis::UserControl) // changed from BaseComponent to UserControl
	{
		NsMeta<Noesis::Core::TypeId>("DataModel");
		NsProp("DataListBoxSourceContainer", &DataModel::m_Container);

		const Noesis::TypeClass* type = Noesis::TypeOf<SelfClass>();
		Noesis::Ptr<Noesis::ResourceKeyType> defaultStyleKey = Noesis::ResourceKeyType::Create(type);
		Noesis::Ptr<Noesis::UIElementData> data = NsMeta<Noesis::UIElementData>(type);
		data->RegisterProperty<NsInt32>(m_CountValue, "COUNT",
			Noesis::FrameworkPropertyMetadata::Create(NsInt32(0), Noesis::FrameworkOptions_None));
	}
	size_t mCount;
};
/// -------------------------------------------------------------------------------------------------------------------
void DataModel::m_func_ContainerAdd()
{
	// ...
	m_SetCount();
}
void DataModel::m_func_ContainerRemove()
{
	// ...
	m_SetCount();
}
// ...
NsInt32 DataModel::m_GetCount() const
{
	return Noesis::DependencyObject::GetValue<NsInt32>(m_CountValue);
}
void DataModel::m_SetCount()
{
	mCount = m_Container->Count();
	Noesis::DependencyObject::SetValue<NsInt32>(m_CountValue, mCount);
}
const Noesis::Gui::DependencyProperty * DataModel::m_CountValue;
In xaml
<TextBlock
				DataContext="{DynamicResource dataModel}"
				Text="{Binding COUNT}"
			/>
Then you see count of your collection.
Btw I tried
<TextBlock
				DataContext="{DynamicResource dataModel}"
				Text="{Binding dataModel.Count, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
			/>
without Noesis::Gui::DependencyProperty * DataModel::m_CountValue in CodeBehind, but it is not working.

Re: Some limitations of ObservableCollection

Posted: 14 Sep 2017, 02:01
by sfernandez
1. No, ObservableCollection doesn't expose any properties to be bound in the ViewModel. But as you said, it can be exposed via the ViewModel.
2. Simple data must be boxed before added to the observable collection:
Ptr<ObservableCollection<BaseComponent>> collection = *new ObservableCollection<BaseComponent>();
Drawing::Point point(1.0f, 0.0f);
auto boxed = Boxing::Box<Drawing::Point>(point);
collection->Add(boxed.GetPtr());
Some considerations with ViewModel design though:
  • ViewModel doesn't need to be a UserControl or any other UI element class. It is usually a simple BaseComponent.
  • You can bind to properties registered in the reflection, there is no need to create new DependencyProperties.
  • Properties can be read-only if you specify only a Getter for the property.
  • It is better if ViewModel is set via code-behind (viewtopic.php?f=3&t=1166&p=6725#p6725) than explicitely set it in the xaml, because then you are coupling UI with a specific data type.
class DataModel: public BaseComponent, public INotifyPropertyChanged
{
public:
  DataModel(): mItemList(*new ObservableCollection())
  {
    mItemList->CollectionChanged() += MakeDelegate(this, &DataModel::OnItemListChanged);
  }
  
  ObservableCollection<ContainerItem>* GetItemList() const { return mItemList.GetPtr(); }
  NsInt GetItemListCount() const { return mItemList->Count(); }

  PropertyChangedEventHandler& PropertyChanged() { return mPropertyChanged; }

private:
  void OnItemListChanged(BaseComponent* sender, NotifyCollectionChangedEventArgs& e)
  {
    mPropertyChanged(this, PropertyChangedEventArgs(NsSymbol("ItemListCount")));
  }
  
private:
  Ptr<ObservableCollection<ContainerItem>> mItemList;
  PropertyChangedEventHandler mPropertyChanged;
  
  NS_IMPLEMENT_INLINE_REFLECTION(DataModel, BaseComponent)
  {
    NsProp("ItemList", &DataModel::GetItemList);
    NsProp("ItemListCount", &DataModel::GetItemListCount);
  }
};

Re: Some limitations of ObservableCollection

Posted: 14 Sep 2017, 03:04
by nikobarli
@Wanderer, thanks for your answer. Yes, it is possible to manually expose the property using either DependencyProperty or a simple INPC (INotifyPropertyChanged) Property.

@sfernandez, thanks. I didn't aware that we can use Boxing to put simple data to observable collection. Thanks for the guideline too. Yes, we are pursuing an MVVM approach where the View is decoupled from VM/M.

Anyway, if it is not difficult, I think you should expose the Count property as it is in WPF for future releases.

Re: Some limitations of ObservableCollection

Posted: 14 Sep 2017, 16:51
by sfernandez
Anyway, if it is not difficult, I think you should expose the Count property as it is in WPF for future releases.
You are right, we just submitted a fix for the next release and Count property will be available to be bound in UI.

Re: Some limitations of ObservableCollection

Posted: 15 Sep 2017, 04:16
by nikobarli
Great. Thanks !

Re: Some limitations of ObservableCollection

Posted: 18 Sep 2017, 18:28
by jsantos
@sfernandez, thanks. I didn't aware that we can use Boxing to put simple data to observable collection
Anyway, we are aware of this limitation and we are working to improve it in the new type architecture. ObservableCollection should support simple structs, having to use a BaseComponent is quite a memory overhead in many scenarios.

Re: Some limitations of ObservableCollection

Posted: 19 Sep 2017, 08:36
by nikobarli
Anyway, we are aware of this limitation and we are working to improve it in the new type architecture. ObservableCollection should support simple structs, having to use a BaseComponent is quite a memory overhead in many scenarios.
Yes, since we will extensively used ObservableCollection in our applications, I think that would be great.