-
-
sfernandez
Site Admin
- Posts: 2056
- Joined:
Re: A few questions about some features
How do you accessed the property? Do you mean in the XAML or by code?
Re: A few questions about some features
In the Xaml file, something like:
when Orientation is not a property of the control.
Code: Select all
< [CustomControl] Orientation="Vertical" />
Re: A few questions about some features
Right now, if you preprocess that XAML with the BuildTool you will get a warning indicating that the property cannot be found in your type.
Yes, XamlPlayer should have a small console showing this kind of logs. Thanks also for this suggestion.
Yes, XamlPlayer should have a small console showing this kind of logs. Thanks also for this suggestion.
Re: A few questions about some features
Hi,
I have a question about memory management in general. I'm spawning controls with their data context in my application code and I'm wondering who "owns" these things once passed to Noesis. Will the framework delete these entities or should I take care of these myself? What is the best practice for this kind of use?
I also have a problem with my custom drop down menu.
The first one is related to Xaml itself I think. I would like the Popup state (open/close) synchronized with a ToggleButton. In addition to that, I'd like the Popup to close when clicking outside. To do so, I've made a property IsMenuOpen in my CustomControl (derived from ContentControl) and bound the Popup's IsOpen and ToggleButton's IsChecked to it. It works as expected. Anyway, to get the second behaviour, I've set Popup's StaysOpen to false. The problem is that the ToggleButton stays toggled when the menu is closed that way. I've done some tests and apparently the Popup does not update the property when closed.
My second problem is a bit more mysterious. As I said, I'm trying to spawn controls from my application code. One of my goals is to fill a StackPanel with a custom control containing a custom drop down menu. But as soon as I try to add one in the Panel (using UIElementCollection::Add), the application crashes. Here are some code snippets:
test.xaml, loaded by the application:
filterBar.xaml
filterCategory.xaml
Note that I've encountered both problems using that ControlTemplate for MenuAnchor (the custom drop down menu) shown in filterCategory.xaml.
Add function
This piece of code is run right after the test.xaml is loaded in the application.
Thanks a lot!
I have a question about memory management in general. I'm spawning controls with their data context in my application code and I'm wondering who "owns" these things once passed to Noesis. Will the framework delete these entities or should I take care of these myself? What is the best practice for this kind of use?
I also have a problem with my custom drop down menu.
The first one is related to Xaml itself I think. I would like the Popup state (open/close) synchronized with a ToggleButton. In addition to that, I'd like the Popup to close when clicking outside. To do so, I've made a property IsMenuOpen in my CustomControl (derived from ContentControl) and bound the Popup's IsOpen and ToggleButton's IsChecked to it. It works as expected. Anyway, to get the second behaviour, I've set Popup's StaysOpen to false. The problem is that the ToggleButton stays toggled when the menu is closed that way. I've done some tests and apparently the Popup does not update the property when closed.
My second problem is a bit more mysterious. As I said, I'm trying to spawn controls from my application code. One of my goals is to fill a StackPanel with a custom control containing a custom drop down menu. But as soon as I try to add one in the Panel (using UIElementCollection::Add), the application crashes. Here are some code snippets:
test.xaml, loaded by the application:
Code: Select all
<Border
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
HorizontalAlignment="Center" VerticalAlignment="Center"
x:Name="PART_BorderTest"
UseLayoutRounding="True">
<FilterBar x:Name="PART_FilterBar" />
</Border>
Code: Select all
<FilterBar
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="FilterBar" x:Name="FilterBar"
UseLayoutRounding="True">
<StackPanel x:Name="PART_CategoryPanel" Orientation="Horizontal" />
</FilterBar>
Code: Select all
<FilterCategory
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="FilterCategory" x:Name="FilterCategory"
UseLayoutRounding="True">
<FilterCategory.Resources>
<ControlTemplate x:Key="MenuAnchorTemplate" TargetType="{x:Type MenuAnchor}">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<ContentPresenter x:Name="PART_HeaderContent"
Content="{Binding HeaderContent, RelativeSource={RelativeSource TemplatedParent}}"/>
<ToggleButton IsChecked="{Binding IsMenuOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</StackPanel>
<Popup x:Name="PART_Popup"
IsOpen="{Binding IsMenuOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Focusable="False"
PlacementTarget="{Binding ElementName=PART_HeaderContent}"
Placement="Bottom"
PopupAnimation="Slide"
VerticalOffset="1"
AllowsTransparency="True"
StaysOpen="True">
<ContentPresenter/>
</Popup>
</StackPanel>
</ControlTemplate>
<Style TargetType="{x:Type MenuAnchor}">
<Setter Property="Template" Value="{StaticResource MenuAnchorTemplate}"/>
</Style>
</FilterCategory.Resources>
<MenuAnchor>
<MenuAnchor.HeaderContent>
<StackPanel Orientation="Horizontal">
<CheckBox/>
<TextBlock Text="{Binding CategoryID, Mode=TwoWay, StringFormat=F2}" />
</StackPanel>
</MenuAnchor.HeaderContent>
<StackPanel x:Name="PART_FilterPanel" Orientation="Vertical"/>
</MenuAnchor>
</FilterCategory>
Add function
Code: Select all
Noesis::Gui::UIElementCollection* pCol = _filtersCategoriesPanel->GetChildren();
if (pCol != nullptr)
{
pCol->Add(pNewCategory);
}
Thanks a lot!
-
-
sfernandez
Site Admin
- Posts: 2056
- Joined:
Re: A few questions about some features
NoesisGUI UI elements take ownership of the objects you set in them. For example, when setting the ContentControl.Content property, the control keeps a reference to its content, so it isn't destroyed while it is being used. The same occurs for a brush set as Control.Background, etc.Hi,
I have a question about memory management in general. I'm spawning controls with their data context in my application code and I'm wondering who "owns" these things once passed to Noesis. Will the framework delete these entities or should I take care of these myself? What is the best practice for this kind of use?
Code: Select all
void SetText(ContentControl* control, const NsChar* text)
{
Ptr<TextBlock> tb = *new TextBlock(text); // Ptr keeps a reference to the new TextBlock (1 ref)
Ptr<Brush> fg = *new SolidColorBrush(Colors::Red()); // Ptr keeps a reference to the new Brush (1 ref)
tb->SetForeground(fg.GetPtr()); // TextBlock grabs a reference to the Brush (2 refs now)
control->SetContent(tb.GetPtr()); // ContentControl grabs a reference to the TextBlock (2 refs now)
}
// Ptrs are out of scope and destroyed, releasing their references. TextBlock and Brush with 1 ref now
I'll take a look at these two problems and let you know when find something.I also have a problem with my custom drop down menu...
Re: A few questions about some features
Alright, thank you very much! 
While you're having a look at my previous problems, I'm trying to use a member of my data context to interrogate a ResourceDictionary.
After some research, I've found that a way to achieve this is to use a converter to turn the argument (in my case an int) into an ImageSource, contained by the ResourceDictionary passed as parameter.
But apparently, the problem comes from line 25: ResDiscs is not found. However, I manage to get the converter and the data model elsewhere in the code.
My Xaml code:
My converter code:
Can you think of a better way to achieve it?
Do you have an idea of what I might be missing?
Thank you again.

While you're having a look at my previous problems, I'm trying to use a member of my data context to interrogate a ResourceDictionary.
After some research, I've found that a way to achieve this is to use a converter to turn the argument (in my case an int) into an ImageSource, contained by the ResourceDictionary passed as parameter.
But apparently, the problem comes from line 25: ResDiscs is not found. However, I manage to get the converter and the data model elsewhere in the code.
My Xaml code:
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="InventoryTile" x:Name="ROOT_InventoryTile">
<UserControl.Resources>
<ResourceDictionary x:Key="ResDics">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Key="ResDics" Source="itemIcons.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<ResourceArgConverter x:Key="ResArgConverter"/>
<InventoryTileModel x:Key="dataModel" ItemID="1" Quantity="42"/>
</UserControl.Resources>
<Border DataContext="{StaticResource dataModel}"
BorderBrush="Gray" BorderThickness="1">
<StackPanel
HorizontalAlignment="Center" VerticalAlignment="Center"
Orientation="Vertical">
<Image Source="{Binding ItemID,
Converter={StaticResource ResArgConverter},
ConverterParameter={StaticResource ResDics}}"
Height="60" Width="60"/>
<TextBlock
HorizontalAlignment="Center"
Text="{Binding Quantity}" />
</StackPanel>
</Border>
</UserControl>
Code: Select all
NsBool TryConvert(Noesis::Core::BaseComponent* value,
const Noesis::Core::Type* targetType,
Noesis::Core::BaseComponent* parameter,
Noesis::Core::Ptr<Noesis::Core::BaseComponent>& result)
{
Noesis::Core::BaseComponent* pResult = nullptr;
if (nullptr != value)
{
Noesis::Gui::ResourceDictionary* pParam = Noesis::Core::Boxing::Unbox<Noesis::Gui::ResourceDictionary*>(parameter);
NsInt32 intKey = Noesis::Core::Boxing::Unbox<NsInt32>(value);
std::string strKey = std::to_string(intKey);
const NsChar* charKey = strKey.c_str();
Noesis::Core::Ptr<Noesis::Gui::ResourceKeyString> pResKeyStr = Noesis::Gui::ResourceKeyString::TryCreate(charKey);
if (nullptr != pParam && 0 != pResKeyStr)
{
pResult = pParam->TryGet(pResKeyStr);
if (nullptr != pResult)
{
result.Reset(pResult);
}
}
}
return nullptr != pResult;
}
Do you have an idea of what I might be missing?
Thank you again.
-
-
sfernandez
Site Admin
- Posts: 2056
- Joined:
Re: A few questions about some features
I see one thing wrong in your converter code. Objects deriving from BaseComponent are not boxed, so you don't need to call Unbox over them, just perform the desired cast:
Let me know if it works this way.
Code: Select all
NsBool TryConvert(Noesis::Core::BaseComponent* value,
const Noesis::Core::Type* targetType,
Noesis::Core::BaseComponent* parameter,
Noesis::Core::Ptr<Noesis::Core::BaseComponent>& result)
{
Noesis::Core::BaseComponent* pResult = nullptr;
if (nullptr != value)
{
// if you are sure of the parameter type use NsStaticCast, if you don't know call NsDynamicCast
// and check for null
Noesis::Gui::ResourceDictionary* pParam = NsStaticCast<Noesis::Gui::ResourceDictionary*>(parameter);
// you can use ToString to get a string representation of a boxed value
Noesis::Core::Ptr<Noesis::Gui::ResourceKeyString> pResKeyStr =
Noesis::Gui::ResourceKeyString::TryCreate(value->ToString().c_str());
if (nullptr != pParam && 0 != pResKeyStr && pParam->Find(pResKeyStr.GetPtr(), pResult))
{
result.Reset(pResult);
return true;
}
}
result.Reset();
return false;
}
Re: A few questions about some features
Oh, that's a good thing to know, thank you. But I cannot even specify the ResourceDictionary as the parameter of the converter. I have an error at that line, telling me that the resource cannot be found.
I've tried to turn the integer into a ResourceKeyString but I did not have much more success that way.
Am I tackling the problem correctly?
I've tried to turn the integer into a ResourceKeyString but I did not have much more success that way.
Am I tackling the problem correctly?
-
-
sfernandez
Site Admin
- Posts: 2056
- Joined:
Re: A few questions about some features
Maybe it is setting the 'ResDics' in the Resources property, but it should show an error of setting the property multiple times. We will improve error checking if no message is shown.
Please try the following in your xaml:
Please try the following in your xaml:
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="InventoryTile" x:Name="ROOT_InventoryTile">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary x:Key="ResDics" Source="itemIcons.xaml"/>
<ResourceArgConverter x:Key="ResArgConverter"/>
<InventoryTileModel x:Key="dataModel" ItemID="1" Quantity="42"/>
</ResourceDictionary>
</UserControl.Resources>
<!-- ... -->
</UserControl>
Re: A few questions about some features
It's working great, thank you so much! 
Actually, it works in the XamlPlayer, but as soon as I try to integrate it in my application, bad things happens.
Here's my minimal file:
As soon as I uncomment the Border resources, I get that error:
Here is the code of my data model but that's a really standard thing and I don't think the problem originate from there:
The weird thing is that everything is working in the XamlPlayer. Do you have a lead on what might be wrong with that? Thank you.
EDIT: I manage to skip the problem by setting the DataContext in the application rather than in the Xaml, but I'd like to make sure I can trust the XamlPlayer at 100% in the future. Knowing what I've done wrong is still very valuable to me.

Actually, it works in the XamlPlayer, but as soon as I try to integrate it in my application, bad things happens.
Here's my minimal file:
Code: Select all
<Border
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Root"
BorderBrush="White" BorderThickness="1"
HorizontalAlignment="Center" VerticalAlignment="Center">
<!--<Border.Resources>
<ResourceDictionary>
<InventoryTileModel x:Key="model" ItemID="0" Quantity="10" />
</ResourceDictionary>
</Border.Resources>-->
<Image
Source="./assets/woodicon.png"
Height="60" Width="60" />
</Border>
Code: Select all
File Core\Kernel\Src\Memory.cpp (l. 130): Not enough memory! (malloc(15627680408))
Code: Select all
class InventoryTileModel : public Noesis::Core::BaseComponent
{
public:
InventoryTileModel()
: _itemID(-1)
, _quantity(-1)
{}
InventoryTileModel(int inID, int inQuantity)
: _itemID(inID)
, _quantity(inQuantity)
{}
~InventoryTileModel() {}
int GetItemID() const { return _itemID; }
void SetItemID(int inID) { _itemID = inID; }
int GetQuantity() const { return _quantity; }
void SetQuantity(int inQuantity) { _quantity = inQuantity; }
/** BaseComponent interface **/
void Serialize(Noesis::Core::SerializationData* data) const;
void Unserialize(Noesis::Core::UnserializationData* data, NsUInt32 version);
/**/
private:
int _itemID;
int _quantity;
NS_IMPLEMENT_INLINE_REFLECTION(InventoryTileModel, Noesis::Core::BaseComponent)
{
NsMeta<Noesis::Core::TypeId>("InventoryTileModel");
NsProp("ItemID", &InventoryTileModel::GetItemID, &InventoryTileModel::SetItemID);
NsProp("Quantity", &InventoryTileModel::GetQuantity, &InventoryTileModel::SetQuantity);
}
};
EDIT: I manage to skip the problem by setting the DataContext in the application rather than in the Xaml, but I'd like to make sure I can trust the XamlPlayer at 100% in the future. Knowing what I've done wrong is still very valuable to me.
Who is online
Users browsing this forum: No registered users and 1 guest