Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

c# - programmatically addressing a canvas created in xaml

I am creating an application in WPF using the MVVM approach. I am fairly new to the topic and I'm looking on pointers how to achieve the following: I have created a canvas in XAML, as follows:

<canvas name = "myCanvas">
...
</canvas>

I added a button, also in XAML, which I want to use to draw (programmatically) some basic shapes (line, rectangle, etc.) onto the existing canvas on mouse click. Since I'm using the MVVM approach, the button's command has to be bound to a method, as follows:

<Button name="myButton" Command="{Binding myMethod, Mode=OneWay}">
...
</Button>

I got the binding itself to work fine and I created the drawings and shapes in C#, but I don't understand how can I put the shapes onto the canvas that was created in XAML. How can I address the canvas pre-made in XAML from my method? How do I go about this?

Edit:

The point of this is that I want to generate shapes based on data to visualise it. So, if my input has, say, 3 elements of type A, I want to create 3 rectangles and display them on the canvas. Later I want to make them clickable and display some information about them on click. MVVM is a set requirement for me.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In your view model you should have a representation of the shapes that does not use any UI elements:

public class ShapeItem
{
    public Geometry Geometry { get; set; }
    public Brush Fill { get; set; }
    public Brush Stroke { get; set; }
}

public class ViewModel
{
    public ObservableCollection<ShapeItem> ShapeItems { get; set; }
}

You would then use an ItemsControl with an appropriate ItemsPanel and ItemTemplate to visualize the shape items:

<ItemsControl ItemsSource="{Binding ShapeItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Path Data="{Binding Geometry}"
                  Fill="{Binding Fill}"
                  Stroke="{Binding Stroke}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The view model might be initialized like shown below, and items may be added similarly when an appropriate command method is executed:

var vm = new ViewModel();
vm.ShapeItems = new ObservableCollection<ShapeItem>();
vm.ShapeItems.Add(
    new ShapeItem
    {
        Geometry = new EllipseGeometry(new Point(100, 100), 100, 50),
        Fill = Brushes.LightBlue
    });
vm.ShapeItems.Add(
    new ShapeItem
    {
        Geometry = new RectangleGeometry(new Rect(150, 100, 200, 100)),
        Fill = Brushes.Azure,
        Stroke = Brushes.Black
    });

DataContext = vm;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...