WPF:将资源元素添加到画布和绑定属性 [英] WPF: Adding resource element to canvas and binding properties

查看:140
本文介绍了WPF:将资源元素添加到画布和绑定属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个在画布上绘制元素的应用程序。这些元素是矩形(但我使用Border类是因为我想在其中插入文本)。这些元素代表对象(在我的案例中为Tasks)。

I have programmed an application that draws elements in a canvas. These elements are Rectangles (but I used the Border class because I want to instert text in it). These elements represent objects (Tasks in my case).

我在代码后面绘制这些元素,如下所示:

I draw these elements in code behind like this:

foreach (var task in TasksList)
{
    var rect = new Border();
    rect.Background = (SolidColorBrush)(new 
        BrushConverter().ConvertFrom("#0074D9"));
    rect.BorderBrush = (SolidColorBrush)(new 
        BrushConverter().ConvertFrom("#001f3f"));
    rect.BorderThickness = new Thickness(2);

    rect.Width = 60;
    rect.Height = 60;
    var t = new TextBlock
    {
        Text = task.Id.ToString(),
        Foreground = new SolidColorBrush(Colors.White),
        HorizontalAlignment = HorizontalAlignment.Center,
        VerticalAlignment = VerticalAlignment.Center
    };
    rect.Child = t; 

    Canvas.SetLeft(rect, coordX);
    Canvas.SetTop(rect, coordY);
    Canvas.Children.Add(rect);
}

需要在后面的代码中设计边框(矩形)。我想将其设计为XAML资源,并在后面的代码中创建此资源的实例。如何做到这一点?
在这种情况下如何使用绑定?例如,在xaml资源中,我需要定义任务的属性ID需要绑定到位于边框中间的TextBlock的Text属性。但是后来,在后面的代码中,如何指定xaml中定义的属性的DataContext?

Insted of designing the border (rect) in code behind. I would like to design it as a XAML resource and create instances of this resources in code behind. How can accomplish this? How can I use bindings in this case? For instance, in the xaml resource I need to define that the property ID of the task needs to be binded to the Text property of a TextBlock placed in the middle of the border. But later, in the code behind, how do I specify the DataContext of the properties defined in the xaml?

希望您可以指导我。谢谢

Hope you could guide me. Thanks

推荐答案

目前尚不清楚坐标值从何而来,所以我将其转换为 TaskItem 类。您可以根据需要更改此方面。

It's not really clear where the coordinate values come from, so I turned them into part of the TaskItem class. You can change this aspect however you may want.

为了在WPF XAML中实现代码,您需要直观地表示该项目( DataTemplate )和确定项目位置的方法-我在这方面使用了一种样式。这些项目将使用Clemens建议的 ItemsControl 放在画布上。

In order to realize your code in WPF XAML, you need a visual representation of the item (DataTemplate) and a way to determine the item placement - I use a style for this aspect. The items will be placed on the canvas with an ItemsControl as suggested by Clemens.

TaskItem是一个普通类对于这个例子。如果要在创建后修改其内容,则最好使用 INotifyPropertyChanged 来实现。

The TaskItem is a plain class for this example. If you want to modify its contents after creation, you should better implement it with INotifyPropertyChanged.

public class TaskItem
{
    public int Id { get; set; }
    public double CoordX { get; set; }
    public double CoordY { get; set; }
}

xaml,期望使用 DataContext 包含 TasksList 集合:

The xaml, expecting the DataContext to contain a TasksList collection:

<Window.Resources>
    <DataTemplate x:Key="dtTaskItem" DataType="{x:Type local:TaskItem}">
        <Border
            Background="#0074D9"
            BorderBrush="#001F3F"
            BorderThickness="2"
            Width="60"
            Height="60">
            <TextBlock
                Text="{Binding Id}"
                Foreground="White"
                HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Border>
    </DataTemplate>

    <Style x:Key="canvasTaskItemStyle" TargetType="ContentPresenter">
        <Setter Property="Canvas.Left" Value="{Binding CoordX}"/>
        <Setter Property="Canvas.Top" Value="{Binding CoordY}"/>
    </Style>
</Window.Resources>
<Grid x:Name="grid1">
    <ItemsControl
        ItemsSource="{Binding TasksList}"
        ItemTemplate="{StaticResource dtTaskItem}"
        ItemContainerStyle="{StaticResource canvasTaskItemStyle}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

还有一些示例数据可用于:

And some example data to play with:

var tasksList = new List<TaskItem>()
{
    new TaskItem { Id = 1, CoordX = 10, CoordY = 20 },
    new TaskItem { Id = 2, CoordX = 60, CoordY = 160 },
    new TaskItem { Id = 5, CoordX = 140, CoordY = 80 },
    new TaskItem { Id = 3, CoordX = 50, CoordY = 50 },
    new TaskItem { Id = 8, CoordX = 100, CoordY = 100 },
};
grid1.DataContext = new { TasksList = tasksList };

侧面说明:资源也可以放置在 Grid.Resources 部分。 Window.Resources 只是测试一些与WPF相关的stackoverflow问题的答案时使用的默认版本。 local:TaskItem 期望为当前项目定义xaml命名空间(在我的情况下 xmlns:local = clr-namespace:WpfTests_2 )。

Sidenote: the resources could as well be placed inside a Grid.Resources section. The Window.Resources is just a default build I use when testing my answers to some WPF related stackoverflow question. The local:TaskItem expects the xaml namespace to be defined for the current project (In my case xmlns:local="clr-namespace:WpfTests_2").

这篇关于WPF:将资源元素添加到画布和绑定属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆