locked
ListBox with a Canvas, strange selection behaviour RRS feed

  • Question

  • Hello,

     

    I have a Listbox with a Canvas asigned to the ItemsPanelTemplate:

    <ListBox x:Name="CanvasListBox" SelectionMode="Multiple" SelectionChanged="CanvasSelectionChanged">
    	<ListBox.ItemsPanel>
    		<ItemsPanelTemplate>
    			<Canvas />
    		</ItemsPanelTemplate>
    	</ListBox.ItemsPanel>
    </ListBox>
    
    Now I can fill the canvas by adding some UIElements. But whenever I select one or more items in the CanvasListBox, the selected area is bigger than expected and always includes the Point at (0,0). So, how can I manipulate the area that is been selected? It seems it's not only dependend on the size of the selected UIElement.

     

    Thank you,
    Christian

    Tuesday, October 26, 2010 1:37 PM

Answers

  • Hi Mr Sparkle,

    At first, we should understand the Visual Tree of a ListBox, please see below diagram:

    Even if we bind the ItemsSource property of the ListBox to a view, it still has the ListBoxItem as a wrapper for each item, we call them "ItemContainer" in WPF. All ItemsControl has the ItemContainer, such as ItemsControl use UIElement as the container, ListView uses ListViewItem, TreeView uses TreeViewItem and ComboBox uses ComboBoxItem etc. If we change the ItemsPanelTemplate of the ListBox to a Canvas, the containers are hosted in the canvas panel directly. (And the specific data template of the ListBox is in the container in the Visual Tree )

    How to arrange the items in the Canvas ListBox? Yes, set the Canvas.Top/Left/Right/Bottom attached properties for the container (ListBoxItem). Not the added UIELement, since the added UIElement is in the container. ItemsControl provides a property - ItemContainerStyle property, we could specify a style for the ListBoxItem to this property, and specify the Canvas attached properties:

      <ListBox ItemsSource="{Binding}">
       <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
         <Canvas/>
        </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
       <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
         <Setter Property="Canvas.Top" Value="{Binding ...}"/>
         <Setter Property="Canvas.Left" Value="..."/>
        </Style>
       </ListBox.ItemContainerStyle>
       <ListBox.ItemTemplate>
        <DataTemplate>
         ......
        </DataTemplate>
       </ListBox.ItemTemplate>
      </ListBox>
    

    so regarding to the bound item, I think you need other two properties to set the Canvas.Top/Left values, and bind them on the Canvas.Top/Lsft attached properties in the Style, then the Item can be rendered to the correct position.

    If you want to change the position of the item in the ListBox as run-time, VisualTreeHelper can help you to get the container, and invoke Canvas.SetLeft/SetTop methods to change the value.

    Hope this helps.

    Sincerely,
    Bob Bao

    MSDN Subscriber Support in Forum 

    If you have any feedback on our support, please contact msdnmg@microsoft.com

     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download all in one code framework !
    • Marked as answer by Jie Bao Wednesday, November 3, 2010 11:21 AM
    Wednesday, October 27, 2010 8:48 AM

All replies

  • Hello Christian

    This is should be canvas layout behaviour. When you add UIElements to ListBox, you can try to call method Canvas.SetLeft(youUI, 20) to set the layout position in canvas panel.

     

    Hope this helps.


    Keep improving.
    Yiling Lai. MVP (Visual C++ and Client App Dev)
    Tuesday, October 26, 2010 3:15 PM
  • Hi Mr Sparkle,

    At first, we should understand the Visual Tree of a ListBox, please see below diagram:

    Even if we bind the ItemsSource property of the ListBox to a view, it still has the ListBoxItem as a wrapper for each item, we call them "ItemContainer" in WPF. All ItemsControl has the ItemContainer, such as ItemsControl use UIElement as the container, ListView uses ListViewItem, TreeView uses TreeViewItem and ComboBox uses ComboBoxItem etc. If we change the ItemsPanelTemplate of the ListBox to a Canvas, the containers are hosted in the canvas panel directly. (And the specific data template of the ListBox is in the container in the Visual Tree )

    How to arrange the items in the Canvas ListBox? Yes, set the Canvas.Top/Left/Right/Bottom attached properties for the container (ListBoxItem). Not the added UIELement, since the added UIElement is in the container. ItemsControl provides a property - ItemContainerStyle property, we could specify a style for the ListBoxItem to this property, and specify the Canvas attached properties:

      <ListBox ItemsSource="{Binding}">
       <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
         <Canvas/>
        </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
       <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
         <Setter Property="Canvas.Top" Value="{Binding ...}"/>
         <Setter Property="Canvas.Left" Value="..."/>
        </Style>
       </ListBox.ItemContainerStyle>
       <ListBox.ItemTemplate>
        <DataTemplate>
         ......
        </DataTemplate>
       </ListBox.ItemTemplate>
      </ListBox>
    

    so regarding to the bound item, I think you need other two properties to set the Canvas.Top/Left values, and bind them on the Canvas.Top/Lsft attached properties in the Style, then the Item can be rendered to the correct position.

    If you want to change the position of the item in the ListBox as run-time, VisualTreeHelper can help you to get the container, and invoke Canvas.SetLeft/SetTop methods to change the value.

    Hope this helps.

    Sincerely,
    Bob Bao

    MSDN Subscriber Support in Forum 

    If you have any feedback on our support, please contact msdnmg@microsoft.com

     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download all in one code framework !
    • Marked as answer by Jie Bao Wednesday, November 3, 2010 11:21 AM
    Wednesday, October 27, 2010 8:48 AM