Search code examples
c#.netcanvasdatatemplatewinui-3

WinUI 3 ListView Linked To Observablecollection contains layer classes derived from class canvas


I want to create an application like photoshop main canvas which groups layer canvases,

a listview which displays the name of the layers and a visibility button via a datatemplate of each layer added to the main canvas.

I created the class layer derived from the class convas

public class Layer : Canvas
{
  public string Name { get; set; }
   public bool IsVisible { get; set; }

   public Layer(Canvas mainCanvas)  {   

      // Initialize layer properties 
      Name = "New Layer";
      IsVisible = true; 
      mainCanvas.Children.Add(this);  
  }
}

ListView Layers :

<StackPanelGrid.Row="1"Orientation="Vertical"> 
    <ListViewx:Name="listViewLayers"x:FieldEdit="public"Background="SeaGreen">
       <ListView.ItemTemplate>
          <DataTemplate x:DataType="Layer">
            <StackPanel>
               <TextBlock Text="{x:Bind Name, Mode=TowWay}" />
            </StackPanel>
       </DataTemplate>
     </ListView.ItemTemplate>
    </ListView>
</StackPanel>

ObservableCollection ocLayers :

ObservableCollection<Layer> ocLayers = new ObservableCollection<Layer>();  
             ocLayers.Add(new Layer(mainCanvas){Name="AAA"});
             ocLayers.Add(new Layer(mainCanvas){Name="BBB"});
             listViewLayers.ItemsSource = ocLayers;
with DataTemplate DataType="Canvas" and ObservableCollection<Canvas>

if i add simple canvas Object just for testing it works

and with DataTemplate DataType="Layer" and ObservableCollection<Layer>

if i add Layer Object execution hangs


Solution

  • I'm not sure why your app is hangs but let mentioned that instead of "Layer is a Canvas", I suggest "Layer has a Canvas". See this post.

    So, it'd be something like this:

    public class Layer
    {
        public string Name { get; set; } = string.Empty;
    
        public Canvas Canvas { get; }
    
        public Layer(Canvas canvas)
        {
            Canvas = canvas;
        }
    }
    

    And add layers like this:

    private void AddLayerButton_Click(object sender, RoutedEventArgs e)
    {
        int layerId = Layers.Count + 1;
        Layer newLayer = new(new Canvas())
        {
            Name = $"New Layer #{layerId}"
        };
        this.mainCanvas.Children.Add(newLayer.Canvas);
        Layers.Add(newLayer);
    }