User avatar
rmcq
Topic Author
Posts: 16
Joined: 18 Feb 2020, 23:31

ItemsControl in Listbox breaks Selection

01 Apr 2020, 08:37

Hi team,

I've got a Listbox populating from a DataTemplate. Inside this Data Template is an ItemsControl.
The ItemsControl has a DataTemplate containing a Canvas with an Ellipse and Textblock. The Canvas positions are databound so we can position them dynamically.
The Listbox contains 5 items. Only 1 of these (the far right) populates the ItemsControl. The others leave it empty. I have bool to show / hide each of these.
Jump into Native and I populate the data. When I run the game, it looks correct visually but I'm no longer able to scroll left/right to select items in the Listbox.
When I comment out the ItemsControl I can select stuff again.

------

Things I've tried:
- Adding gamepad triggers for Left/Right. I already had these for Up/Down. When I add a breakpoint, Up/Down still get hit but Left/Right don't.
- Adding a DataTemplateSelector so that only the last ListBoxItem has an ItemsControl. I was following the code from this post but breakpoints in the constructor and bound functions never seem to get hit:
viewtopic.php?f=3&t=663&hilit=datatempl ... t=10#p3706
I thought may I need to register it as a component like our extensions but that didn't help either.

------

XAML (before DataTemplateSelector):
<Grid
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
	xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
	xmlns:local="clr-namespace:MatchSettings"
	xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="RootGrid" Focusable="True"
	mc:Ignorable="d"
	d:DataContext="{d:DesignInstance {x:Type local:MatchSettingsVM}, IsDesignTimeCreatable=True}"
>
	<Grid.DataContext>
		<local:MatchSettingsVM/>
	</Grid.DataContext>

	<Grid.Resources>
		<DataTemplate x:Key="MatchSettingsTemplate">
			<Grid>
				<Grid Height="328" Width="204" Margin="0,-200,9,0" Visibility="{Binding IconIsVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
					<ItemsControl
						ItemsSource="{Binding Players}"
					>
						<ItemsControl.ItemTemplate>
							<DataTemplate>
								<Canvas>
									<Grid Height="42" Width="42" Canvas.Left="{Binding XPos}" Canvas.Top="{Binding YPos}">
										<Ellipse Stroke="White">
											<Ellipse.Fill>
												<SolidColorBrush Color="{Binding Colour}"/>
											</Ellipse.Fill>
										</Ellipse>
										<TextBlock TextWrapping="Wrap" FontSize="24" TextAlignment="Center" Text="{Binding Label}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
									</Grid>
								</Canvas>
							</DataTemplate>
						</ItemsControl.ItemTemplate>
					</ItemsControl>
				</Grid>
			</Grid>
		</DataTemplate>
    </Grid.Resources>
	<Viewbox>
		<Grid Width="1920" Height="1080">
			<Viewbox x:Name="viewbox" Stretch="Fill" RenderTransformOrigin="0.5,0.5">
				<Viewbox.RenderTransform>
					<TransformGroup>
						<ScaleTransform/>
						<SkewTransform/>
						<RotateTransform/>
						<TranslateTransform/>
					</TransformGroup>
				</Viewbox.RenderTransform>
				<Grid Height="1080" Width="1920">
					<Grid Grid.Column="0">
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="*"/>
						</Grid.ColumnDefinitions>
						<Grid.RowDefinitions>
							<RowDefinition Height="130*"/>
							<RowDefinition Height="820*"/>
							<RowDefinition Height="130*"/>
						</Grid.RowDefinitions>

						<Grid Grid.Row="1" Margin="253.25,72.25,256.75,12.75">
							<Grid.ColumnDefinitions>
								<ColumnDefinition Width="*"/>
							</Grid.ColumnDefinitions>
							<Grid.RowDefinitions>
								<RowDefinition Height="*"/>
							</Grid.RowDefinitions>

							<Grid Margin="5,0,0,0">
								<Viewbox Margin="0,0,3,0">
									<ListBox x:Name="MatchSettingsGrid"
										ItemsSource="{Binding MatchSettingsList}"
										SelectedItem="{Binding SelectedItem, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
										SelectedIndex="{Binding SelectedIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
										ScrollViewer.HorizontalScrollBarVisibility="Disabled"
										ScrollViewer.VerticalScrollBarVisibility="Disabled"
										ItemTemplate="{StaticResource MatchSettingsTemplate}"
										Focusable="True"
										Background="Transparent"
										BorderBrush="Transparent"
										KeyboardNavigation.ControlTabNavigation="None" RenderTransformOrigin="0.5,0.5"
									>
										<ListBox.RenderTransform>
											<TransformGroup>
												<ScaleTransform/>
												<SkewTransform/>
												<RotateTransform/>
												<TranslateTransform/>
											</TransformGroup>
										</ListBox.RenderTransform>
										<ListBox.ItemsPanel>
											<ItemsPanelTemplate>
												<UniformGrid Rows="1" />
											</ItemsPanelTemplate>
										</ListBox.ItemsPanel>
									</ListBox>
								</Viewbox>
							</Grid>
						</Grid>
					</Grid>
				</Grid>
			</Viewbox>
		</Grid>
	</Viewbox>
	<i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <ei:PlaySoundAction Source="scroll" Volume="1.0"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Loaded">
            <noesis:SetFocusAction TargetName="MatchSettingsGrid"/>
            <i:InvokeCommandAction Command="{Binding FindStoryboardsCommand}" />
        </i:EventTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Accept">
            <ei:PlaySoundAction Source="select" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandForward}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Cancel">
            <ei:PlaySoundAction Source="select" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandBack}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Up">
            <ei:PlaySoundAction Source="slider" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandKeyUp}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Down">
            <ei:PlaySoundAction Source="slider" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandKeyDown}"/>
        </noesis:GamepadTrigger>
		<noesis:GamepadTrigger FiredOn="ButtonDown" Button="Left">
			<ei:PlaySoundAction Source="slider" Volume="1.0"/>
			<i:InvokeCommandAction Command="{Binding CommandKeyLeft`}"/>
		</noesis:GamepadTrigger>
		<noesis:GamepadTrigger FiredOn="ButtonDown" Button="Right">
			<ei:PlaySoundAction Source="slider" Volume="1.0"/>
			<i:InvokeCommandAction Command="{Binding CommandKeyRight`}"/>
		</noesis:GamepadTrigger>
	</i:Interaction.Triggers>
    <Grid.InputBindings>
        <KeyBinding Key="Esc" Command="{Binding CommandBack}"/>
        <KeyBinding Key="Enter" Command="{Binding CommandForward}"/>
    </Grid.InputBindings>
</Grid>
XAML (after DataTemplateSelector):

<Grid
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
	xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
	xmlns:local="clr-namespace:MatchSettings"
	xmlns:dt="clr-namespace:DataTemplates"
	xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="RootGrid" Focusable="True"
	mc:Ignorable="d"
	d:DataContext="{d:DesignInstance {x:Type local:MatchSettingsVM}, IsDesignTimeCreatable=True}"
>
	<Grid.DataContext>
		<local:MatchSettingsVM/>
	</Grid.DataContext>

	<Grid.Resources>
		<DataTemplate x:Key="MatchSettingsTemplate">
			...
		 </DataTemplate>

		<DataTemplate x:Key="MatchSettingsIconTemplate">
			<Grid>
				<Grid Height="328" Width="204" Margin="0,-200,9,0" Visibility="{Binding IconIsVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
					<ItemsControl
						ItemsSource="{Binding Players}"
					>
						<ItemsControl.ItemTemplate>
							<DataTemplate>
								<Canvas>
									<Grid Height="42" Width="42" Canvas.Left="{Binding XPos}" Canvas.Top="{Binding YPos}">
										<Ellipse Stroke="White">
											<Ellipse.Fill>
												<SolidColorBrush Color="{Binding Colour}"/>
											</Ellipse.Fill>
										</Ellipse>
										<TextBlock TextWrapping="Wrap" FontSize="24" TextAlignment="Center" Text="{Binding Label}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
									</Grid>
								</Canvas>
							</DataTemplate>
						</ItemsControl.ItemTemplate>
					</ItemsControl>
				</Grid>
			</Grid>
		</DataTemplate>

		<dt:MatchSettingsTemplateSelector x:Key="matchSettingsTemplateSelector" 
			MatchSettingsTemplate="{StaticResource MatchSettingsTemplate}" 
			MatchSettingsIconTemplate="{StaticResource MatchSettingsIconTemplate}"
		/>

    </Grid.Resources>

	<Viewbox>
		<Grid Width="1920" Height="1080">
			<Viewbox x:Name="viewbox" Stretch="Fill" RenderTransformOrigin="0.5,0.5">
				<Viewbox.RenderTransform>
					<TransformGroup>
						<ScaleTransform/>
						<SkewTransform/>
						<RotateTransform/>
						<TranslateTransform/>
					</TransformGroup>
				</Viewbox.RenderTransform>
				<Grid Height="1080" Width="1920">
					<Grid Grid.Column="0">
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="*"/>
						</Grid.ColumnDefinitions>
						<Grid.RowDefinitions>
							<RowDefinition Height="130*"/>
							<RowDefinition Height="820*"/>
							<RowDefinition Height="130*"/>
						</Grid.RowDefinitions>
						<Grid Grid.Row="1" Margin="253.25,72.25,256.75,12.75">
							<Grid.ColumnDefinitions>
								<ColumnDefinition Width="*"/>
							</Grid.ColumnDefinitions>
							<Grid.RowDefinitions>
								<RowDefinition Height="*"/>
							</Grid.RowDefinitions>

							<Grid Margin="5,0,0,0">
								<Viewbox Margin="0,0,3,0">
									<ListBox x:Name="MatchSettingsGrid"
										ItemsSource="{Binding MatchSettingsList}"
										SelectedItem="{Binding SelectedItem, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
										SelectedIndex="{Binding SelectedIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
										ScrollViewer.HorizontalScrollBarVisibility="Disabled"
										ScrollViewer.VerticalScrollBarVisibility="Disabled"
										ItemTemplateSelector="{StaticResource matchSettingsTemplateSelector}"
										Focusable="True"
										Background="Transparent"
										BorderBrush="Transparent"
										KeyboardNavigation.ControlTabNavigation="None" RenderTransformOrigin="0.5,0.5"
									>
										<ListBox.RenderTransform>
											<TransformGroup>
												<ScaleTransform/>
												<SkewTransform/>
												<RotateTransform/>
												<TranslateTransform/>
											</TransformGroup>
										</ListBox.RenderTransform>
										<ListBox.ItemsPanel>
											<ItemsPanelTemplate>
												<UniformGrid Rows="1" />
											</ItemsPanelTemplate>
										</ListBox.ItemsPanel>
									</ListBox>
								</Viewbox>
							</Grid>
						</Grid>
					</Grid>
				</Grid>
			</Viewbox>
		</Grid>
	</Viewbox>
	<i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <ei:PlaySoundAction Source="scroll" Volume="1.0"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Loaded">
            <noesis:SetFocusAction TargetName="MatchSettingsGrid"/>
            <i:InvokeCommandAction Command="{Binding FindStoryboardsCommand}" />
        </i:EventTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Accept">
            <ei:PlaySoundAction Source="select" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandForward}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Cancel">
            <ei:PlaySoundAction Source="select" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandBack}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Up">
            <ei:PlaySoundAction Source="slider" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandKeyUp}"/>
        </noesis:GamepadTrigger>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Down">
            <ei:PlaySoundAction Source="slider" Volume="1.0"/>
            <i:InvokeCommandAction Command="{Binding CommandKeyDown}"/>
        </noesis:GamepadTrigger>
    </i:Interaction.Triggers>
    <Grid.InputBindings>
        <KeyBinding Key="Esc" Command="{Binding CommandBack}"/>
        <KeyBinding Key="Enter" Command="{Binding CommandForward}"/>
    </Grid.InputBindings>
</Grid>
DataTemplateSelector header
#pragma once
#include "NsGui/DataTemplateSelector.h"

namespace Noesis
{
	class DataTemplate;
	class DependencyObject;
}

namespace paNoesisExtensions
{
	class paMatchSettingsTemplateSelector : public Noesis::DataTemplateSelector
	{
		public:
		paMatchSettingsTemplateSelector();
		virtual Noesis::DataTemplate* SelectTemplate(BaseComponent* item, Noesis::DependencyObject* container) override;
		NS_DECLARE_REFLECTION(paMatchSettingsTemplateSelector, Noesis::DataTemplateSelector)

		Noesis::DataTemplate* GetMatchSettingsTemplate() const;
		void SetMatchSettingsTemplate(Noesis::DataTemplate* dataTemplate);

		private:
		Noesis::Ptr<Noesis::DataTemplate> m_matchSettingsTemplate;
		Noesis::Ptr<Noesis::DataTemplate> m_matchSettingsIconTemplate;

	};
}
DataTemplateSelector source
#include "pch.h"
#include "paMatchSettingsTemplateSelector.h"
#include "NsGui/DataTemplate.h"
#include "NsGui/DependencyObject.h"

paNoesisExtensions::paMatchSettingsTemplateSelector::paMatchSettingsTemplateSelector()
{
	m_matchSettingsTemplate = Noesis::MakePtr<Noesis::DataTemplate>();
	m_matchSettingsIconTemplate = Noesis::MakePtr<Noesis::DataTemplate>();
}

Noesis::DataTemplate* paNoesisExtensions::paMatchSettingsTemplateSelector::SelectTemplate(BaseComponent* item, Noesis::DependencyObject* container)
{
	return m_matchSettingsTemplate;
}

Noesis::DataTemplate* paNoesisExtensions::paMatchSettingsTemplateSelector::GetMatchSettingsTemplate() const
{
	return m_matchSettingsTemplate;
}

void paNoesisExtensions::paMatchSettingsTemplateSelector::SetMatchSettingsTemplate(Noesis::DataTemplate* dataTemplate)
{
	m_matchSettingsTemplate.Reset(dataTemplate);
}

//-----------------------------

NS_BEGIN_COLD_REGION

NS_IMPLEMENT_REFLECTION(paNoesisExtensions::paMatchSettingsTemplateSelector)
{
	NsMeta<Noesis::TypeId>("MatchSettingsTemplateSelector");
	NsProp("MatchSettingsTemplate", &paNoesisExtensions::paMatchSettingsTemplateSelector::GetMatchSettingsTemplate, &paNoesisExtensions::paMatchSettingsTemplateSelector::SetMatchSettingsTemplate);
	NsProp("MatchSettingsIconTemplate", &paNoesisExtensions::paMatchSettingsTemplateSelector::m_matchSettingsIconTemplate);
}
------

Any help would be appreciated.

Thank you,
R
 
User avatar
rmcq
Topic Author
Posts: 16
Joined: 18 Feb 2020, 23:31

Re: ItemsControl in Listbox breaks Selection

08 Apr 2020, 09:59

Hey, sorry for the bump. It's been a week. Do you have any ideas or need any more info from me?
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: ItemsControl in Listbox breaks Selection

08 Apr 2020, 12:08

Hey, sorry for the bump. It's been a week. Do you have any ideas or need any more info from me?
My sorry, we should have answered sooner.
The Listbox contains 5 items. Only 1 of these (the far right) populates the ItemsControl. The others leave it empty. I have bool to show / hide each of these.
Jump into Native and I populate the data. When I run the game, it looks correct visually but I'm no longer able to scroll left/right to select items in the Listbox.
When I comment out the ItemsControl I can select stuff again.
When you say scroll left/right I guess you mean moving the selection (focus) between ListBox items, right?
Have you tried to make the ItemsControl Focusable="False", so keyboard focus doesn't stop on that inner control?
Adding gamepad triggers for Left/Right. I already had these for Up/Down. When I add a breakpoint, Up/Down still get hit but Left/Right don't.
If this was a problem with the focus, gamepad triggers wouldn't work either.
Adding a DataTemplateSelector so that only the last ListBoxItem has an ItemsControl. I was following the code from this post but breakpoints in the constructor and bound functions never seem to get hit: viewtopic.php?f=3&t=663&hilit=datatempl ... t=10#p3706
I thought may I need to register it as a component like our extensions but that didn't help either.
This should work fine once you register your DataTemplateSelector in the factory (so parser could create it).
Have you noticed if there was an error while loading that xaml saying: "Unknown type 'DataTemplates.MatchSettingsTemplateSelector'"?
Maybe you forgot to add the NsMeta<TypeId>("DataTemplates.MatchSettingsTemplateSelector") in the reflection block of that class.
 
User avatar
rmcq
Topic Author
Posts: 16
Joined: 18 Feb 2020, 23:31

Re: ItemsControl in Listbox breaks Selection

14 Apr 2020, 05:57

Wow I feel like a dumb-dumb. All I needed was the Focusable="False". Thanks for the answers.
 
User avatar
jsantos
Site Admin
Posts: 3907
Joined: 20 Jan 2012, 17:18
Contact:

Re: ItemsControl in Listbox breaks Selection

14 Apr 2020, 14:49

Thanks, closing this.

Who is online

Users browsing this forum: Ahrefs [Bot] and 2 guests