Parent null when using ItemsSource binding
I've just started messing around with NoesisGUI, I have no prior experience with XAML/WPF so excuse me if this is rather obvious. I seem to have the same issue this topic mentioned. I've done as suggested and added a check in the Loaded event as follows which reports null.
Here's the relevant XAML
Thank you for your help!
Code: Select all
public partial class WindowView : UserControl {
public WindowView() {
WeakReference weak = new WeakReference(this);
this.Loaded += (s, e) => { ((WindowView)weak.Target)?.OnReportParent(s, e); };
InitializeComponent();
}
private void OnReportParent(object sender, RoutedEventArgs args) {
var winView = (WindowView)sender;
Debug.Log(winView.Parent);
}
Code: Select all
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
xmlns:local="clr-namespace:Game.UI">
<Canvas x:Name="Desktop">
<!-- This one works as expected reporting Desktop as parent !-->
<local:WindowView Width="100" Height="200" />
<!-- These instances always have a null parent !-->
<ItemsControl x:Name="ActiveWindows" ItemsSource="{Binding Windows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:WindowView Width="{Binding Width}" Height="{Binding Height}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</UserControl>
Re: Parent null when using ItemsSource binding
I discovered I can navigate by using VisualTreeHelper.GetParent and I can use ItemsControl.ItemPanel to create the "Desktop" canvas as the parent of the generated elements. Though it seems ItemsPanelTemplate also instances the canvas as a child of a ContentPresenter, like it does with ItemsSource, causing the below reference to a parent grid to fail.
I was trying to get MouseDragElementBehavior ConstrainToParentBounds="True" to work with the ItemsSource elements but even with the above this still fails. I think in this case I'm better off handling the element creation in C# code?
I'm quite enjoying NoesisGUI too, great work!
Code: Select all
<Grid>
...
<ItemsControl x:Name="ActiveWindows" ItemsSource="{Binding Windows}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Blue" Name="Desktop" Grid.Row="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
...
</Grid>
I'm quite enjoying NoesisGUI too, great work!
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: Parent null when using ItemsSource binding
Hi,
The root of a template won't ever have a logical parent, only a visual parent. In the following document you will find more information on the differences between Logical and Visual trees: https://www.noesisengine.com/docs/Gui.C ... tTree.html
The ItemsPanel defines the template used by an ItemsControl to create the hosting panel for the items. You don't have to manually create it, as the control itself will do it when loaded. But that panel will be the parent of the item containers (which are ContentPresenter elements in the case of an ItemsControl). For example, for a xaml like this:
The hierarchy will look something like this:
Why do you need access to the Canvas defined in ItemsControl from the WindowView? Maybe I can help more If I understand what you are trying to do with that.
The root of a template won't ever have a logical parent, only a visual parent. In the following document you will find more information on the differences between Logical and Visual trees: https://www.noesisengine.com/docs/Gui.C ... tTree.html
The ItemsPanel defines the template used by an ItemsControl to create the hosting panel for the items. You don't have to manually create it, as the control itself will do it when loaded. But that panel will be the parent of the item containers (which are ContentPresenter elements in the case of an ItemsControl). For example, for a xaml like this:
Code: Select all
<ItemsControl ItemsSource="{Binding Windows}">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<Border>
<ItemsPresenter/>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:WindowView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Code: Select all
ItemsControl
-- Border (part of ItemsControl template)
---- ItemsPresenter (part of ItemsControl template)
------ Canvas (the panel in ItemsPanel template)
-------- ContentPresenter (item container)
---------- local:WindowView (from ItemTemplate template)
Who is online
Users browsing this forum: No registered users and 93 guests