jerry
Topic Author
Posts: 2
Joined: 24 Oct 2019, 05:44

Parent null when using ItemsSource binding

08 May 2022, 06:46

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.
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);
	}
Here's the relevant XAML
<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>
Thank you for your help!
 
jerry
Topic Author
Posts: 2
Joined: 24 Oct 2019, 05:44

Re: Parent null when using ItemsSource binding

09 May 2022, 12:55

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.
<Grid>
...
<ItemsControl x:Name="ActiveWindows" ItemsSource="{Binding Windows}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <Canvas Background="Blue" Name="Desktop" Grid.Row="1" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  ...
</Grid>
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!
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Parent null when using ItemsSource binding

12 May 2022, 18:56

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:
<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>
The hierarchy will look something like this:
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)
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.

Who is online

Users browsing this forum: No registered users and 93 guests