0

Let me state problem first. I would like to implement wrapper around Canvas (let me call it Page) which would implement selecting rectangle around its UIElements which are actually selected. For this I implemented ISelect interface like so :

interface ISelect {
  Point Center {get; set;} //Center of selecting rectangle
  Size Dimensions {get; set;} //Dimensions of selecting rectangle
}

Every object that is put to Page implements ISelect interface. Page has SelectedElements of type ObservableCollection which holds reference to all currently selected elements.

For every entry in SelectedElements i would like to draw rectangle around it.

I have few ideas how to do this :

  1. Every UIElement can implement on its own this rectangle and show it when selected. This option would require for new objects to implement this every time. So I rather not use it.
  2. In Page I could create rectangles in code-behind in add them to the Page. It isn't MVVM recommended priniciple.
  3. In Page XAML create somehind like ItemsControl and bind it to SelectedElements with specific template. This option seems like the best one to me. Please help me in this direction. Should I somehow use ItemsControl?

Thank you.

ZgHrvoje
  • 11
  • 3
  • Search for adorners (to visualize selection). Or if you prefer individual selection, then instead of adding visuals to `Canvas` directly you can host each inside `Border` (using data templates) which visibility is bound to `IsSelected` property of that visual's view model. – Sinatr Feb 19 '16 at 12:54
  • Hi. Thanks for quick response. Is there any example of your approach? – ZgHrvoje Feb 19 '16 at 13:01

1 Answers1

0

I don't have time to dig a complete working solution, so this is mostly a collection of suggestions.

Each element should have view model

public abstract class Element: INotifyPropertyChanged
{
    bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            OnPropertyChanged();
        }
    }
}

public class EllipseElement : Element {}
public class RectangleElement : Element {}

Then there are data templates to visualize elements (I can't give you converter code, but you can replace it with another, look here).

    <DataTemplate DataType="{x:Type local:EllipseElement}">
        <Border Visibility="{Binding IsSelected, Converter={local:FalseToHiddenConverter}}">
            <Ellipse ... />
        </Border>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:RectangleElement}">
        <Border Visibility="{Binding IsSelected, Converter={local:FalseToHiddenConverter}}">
            <Rectangle ... />
        </Border>
    </DataTemplate>

Then bind ObservableCollection of elements to canvas (which is tricky, see this answer, where ItemsControl is used to support binding).

Your selection routine has to hit-test elements and set/reset their IsSelected property, which will show border. See here regarding how to draw over-all selection rectangle.

Community
  • 1
  • 1
Sinatr
  • 20,892
  • 15
  • 90
  • 319