3

我正在尝试创建和使用自定义画布。这是 XAML (MyCanvas.xaml):

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Core="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Namespace="clr-namespace:MyNamepace" xmlns:Properties="clr-namespace:MyNamepace.Properties" Core:Class="MyNamepace.MyCanvas">
    <Canvas.Resources>
        <Namespace:ImagesConverter Core:Key="ImagesConverter"/>
    </Canvas.Resources>
    <Image Source="{Binding Source={Core:Static Properties:Resources.Background}, Converter={StaticResource ImagesConverter}}" Stretch="Fill"/>
</Canvas>

这是代码声明 (MyCanvas.xaml.cs):

public partial class MyCanvas : Canvas

当我尝试像这样使用它时:

<Namespace:MyCanvas Core:Name="Layout" Loaded="OnLoaded">
    <Namespace:MyUserControl Core:Name="Control1" Namespace:MyCanvas.Left="50" MyProperty="50">
        <Namespace:MyCanvas.Top>
            <MultiBinding Converter="{StaticResource MathConverter}" ConverterParameter="(x - y) / 2">
                <Binding ElementName="Layout" Path="ActualHeight"/>
                <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </Namespace:MyCanvas.Top>
    </Namespace:MyUserControl>
    <Namespace:MyUserControl Core:Name="Control2" Namespace:MyCanvas.Left="744" Namespace:MyCanvas.Top="42" MyProperty="150"/>
</Namespace:MyCanvas>

我得到两个不同的错误:

“内容”属性只能设置一次。==> 不是继承Canvas吗?!?!?!

成员“Top”无法识别或无法访问。==> 不是又继承了Canvas吗?!?!?!成员“Left”无法识别或无法访问。==> 不是又继承了Canvas吗?!?!?!

编辑:这是我到目前为止......仍然得到“内容”已经设置错误!

MyCanvas.xaml

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Core="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Namespace="clr-namespace:MyNamespace" xmlns:Properties="clr-namespace:MyNamespace.Properties" Core:Class="MyNamespace.MyCanvas">
    <Canvas.Background>
        <ImageBrush ImageSource="{Binding Source={Core:Static Properties:Resources.Background}, Converter={StaticResource ImagesConverter}}" Stretch="Fill"/>
    </Canvas.Background>
    <Canvas.Resources>
        <Namespace:ImagesConverter Core:Key="ImagesConverter"/>
    </Canvas.Resources>
</Canvas>

MyCanvas.xaml.cs

public class MyCanvas : Canvas
{
    // ...
}

主窗口.xaml

<Namespace:MyCanvas Core:Name="MyCanvas" Loaded="OnLoaded">
    <Namespace:MyUserControl ...
    <Namespace:MyUserControl ...
    <Namespace:MyUserControl ...
</Namespace:MyCanvas>
4

2 回答 2

4

Left并且Top附加属性。这意味着它们不会被您的类继承。

您需要更改用户控件声明以使用Canvas.LeftCanvas.Top而不是:

<Namespace:MyUserControl Core:Name="Control2" Canvas.Left="744" Canvas.Top="42" 
                         MyProperty="150"/>

内容的问题是您设置了两次,就像错误消息所说的那样。

  1. MyCanvas.xaml您将其设置为Image.
  2. 使用它时,您将其设置为您的用户控件。

要修复它,您需要添加一个ItemsControltoMyCanvas并将其声明为表示内容的控件:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Core="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Namespace="clr-namespace:MyNamepace" xmlns:Properties="clr-namespace:MyNamepace.Properties" Core:Class="MyNamepace.MyCanvas">
    <Canvas.Resources>
        <Namespace:ImagesConverter Core:Key="ImagesConverter"/>
    </Canvas.Resources>
    <Image Source="{Binding Source={Core:Static Properties:Resources.Background}, Converter={StaticResource ImagesConverter}}" Stretch="Fill"/>
    <ItemsControl Content="{Binding Path=LocalContent, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Namespace:MyCanvas}}}" />
</Canvas>

在你的类文件中:

[ContentProperty("LocalContent")]
public partial class MyCanvas : Canvas
{
    public static readonly DependencyProperty LocalContentProperty =
        DependencyProperty.Register(
            "LocalContent", 
            typeof(UIElementCollection), 
            typeof(MyCanvas ), 
            new PropertyMetadata(default(UIElementCollection)));
}
于 2013-02-07T13:23:52.827 回答
4

添加到丹尼尔的回答中,您必须了解 WPF 引入了一个名为“依赖属性”和“依赖对象”的概念。简而言之,就像 C# 中的对象可以具有属性一样,WPF 中的依赖对象也可以具有依赖属性。尽管 c# 方法的工作方式有点不同。

对于依赖属性(例如附加属性),WPF 管理一个单独的表,其中包含指示哪些对象具有哪些属性的记录。换句话说,这意味着任何对象都可能具有任何属性,WPF 只是将一条记录添加到表中,为所述对象提供所述属性。例如,Canvas.Left 虽然由 Canvas定义,但可以由任何控件实现。WPF 只是将一条记录插入到依赖关系表中,瞧现在您的图像具有 Canvas.Left / Canvas.Top 属性。这意味着更小的内存占用,因为对象选择拥有一个属性(当添加记录时),而不是仅仅因为它派生自某个类而拥有一个属性。

以编程方式工作的方式是您使用 DependencyObject.SetValue / GetValue (所有 WPF 对象都派生自 DependencyObject 请参阅: http: //miteshsureja.blogspot.com/2011/06/wpf-class-hierarchy.html - 事实上,记住这一点图表,因为它将帮助您更好地了解 WPF 在后台是如何工作的),这会将记录添加/读取到上述表中。当您定义依赖项属性时,您的 c# 访问器应该真正重定向到这些方法,因为 WPF(而不是对象本身)应该管理这些值(这就是 WPF 能够进行数据绑定的方式,而不是什么,因为它管理这些值并根据需要将它们转移到其他对象)。有关创建依赖属性的示例,请参阅:http: //msdn.microsoft.com/en-us/library/ms752914.aspx. 依赖属性背后的概念非常简单,但您至少必须了解它才能理解很多 WPF 功能。

于 2013-02-07T13:36:53.990 回答