0

Edit 2: This is the original version of the question. Other revisions were made, but this is the only one which properly shows the problem.

Similar questions:

As in the first question above, I'm trying to build a 2D world. My sprites happen to be vector graphics expressed as XAML files, but I doubt that matters. Anyway, I can't get anything beyond a white background.

I tried adding my sprites directly to the canvas in XAML, and that worked fine, but I need them procedurally generated. I looked at the window in Snoop and saw that the canvas isn't actually rendering at all; it's just the window itself.

Why aren't my sprites showing up?

MainWindow.xaml

<Window x:Class="Canvas_test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="Self"
        Title="MainWindow" Height="350" Width="525">
    <ItemsControl ItemsSource="{Binding Sprites, ElementName=Self}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Left" Value="{Binding X}" />
                <Setter Property="Canvas.Top" Value="{Binding Y}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</Window>

MainWindow.xaml.cs

using System.Collections.ObjectModel;
using System.Windows;

namespace Canvas_test {
    public partial class MainWindow : Window {
        public ObservableCollection<Character> Sprites { get; private set; } = new ObservableCollection<Character>();

        public MainWindow() {
            InitializeComponent();

            Sprites.Add(new Character());
        }
    }
}

Character.xaml

<Viewbox x:Class="Canvas_test.Character"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Width="64"
         Height="64"
         Stretch="Uniform">
    <Canvas Width="64" Height="64">
        <Ellipse xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="64" Height="64" Fill="#FF0000FF"/>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#FFFF0000" Data="M 32 0 64 66.25 l -64 0 z" RenderTransform="0.5 0 0 0.9 16 0" />
    </Canvas>
</Viewbox>

Character.xaml.cs

using System.Windows.Controls;

namespace Canvas_test {
    public partial class Character : Viewbox {
        public double X { get; } = 100;
        public double Y { get; } = 100;
    }
}
Community
  • 1
  • 1
Grault
  • 974
  • 12
  • 31
  • 1
    1) You do not have a DataContext to your main window, You can see it from Snoop that there is data binding error. 2) You are adding a view to your ViewModel ... Please try to fix that and tell us what happened. – tgpdyk Dec 11 '15 at 01:33

2 Answers2

2

You must set the DataContext. Here you go:

MainWindow.xaml

<Window x:Class="Canvas_test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        >
    <ItemsControl ItemsSource="{Binding Sprites}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

</Window>

MainWindow.xaml.cs stays the same

Character.xaml

<Viewbox x:Class="Canvas_test.Character"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Width="64"
         Height="64"
         Stretch="Uniform"
         DataContext="{Binding RelativeSource={RelativeSource Self}}"
         Canvas.Top="{Binding Y}"
         Canvas.Left="{Binding X}"
         >
    <Canvas Width="64" Height="64">
        <Ellipse Width="64" Height="64" Fill="#FF0000FF"/>
        <Path Fill="#FFFF0000" Data="M 32 0 64 66.25 l -64 0 z" RenderTransform="0.5 0 0 0.9 16 0" />
    </Canvas>
</Viewbox>

Character.xaml.cs (Initialize the components)

namespace Canvas_test
{
    /// <summary>
    /// Interaction logic for Character.xaml
    /// </summary>
    public partial class Character : Viewbox
    {

        public Character()
        {
            InitializeComponent();
        }

        public double X { get; } = 100;
        public double Y { get; } = 100;
    }
}

Output:

enter image description here

Just an advise, try to use the MVVM pattern.

Dave
  • 473
  • 3
  • 8
  • Somehow I am not getting this result. Furthermore, I see no reason for the DataContext to be relevant when I'm not using unqualified bindings. But I have it in the code right now anyway. – Grault Dec 11 '15 at 02:19
  • Aha, after simplifying my Character class I made the mistake of removing its constructor, forgetting about InitializeComponent. This is indeed the proper fix. Oddly, I feel sure I had a DataContext before minimizing the code. – Grault Dec 11 '15 at 02:24
0

Have you tried IsItemsHost property?

        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True"/>
        </ItemsPanelTemplate>
heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • I did, but it had no effect and I read the documentation as saying it's irrelevant in this case: `Alternatively, you can set the ItemsControl.ItemsPanel property.` https://msdn.microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.110).aspx – Grault Dec 11 '15 at 02:15