2013-02-07 43 views
3

我正在尝试创建和使用自定义画布。这里是XAML(MyCanvas.xaml):定制WPF/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吗?!?!?! 成员“左”未被识别或无法访问。 ==>它不是继承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 
{ 
    // ... 
} 

MainWindow.xaml

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

回答

4

LeftTopattached properties。这意味着它们不会被你的班级继承。

您需要更改用户控件声明使用Canvas.LeftCanvas.Top代替:

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

与内容的问题是,你设置了两次,就像错误消息指出。

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

为了解决这个问题,你需要添加一个ItemsControlMyCanvas并宣布它作为代表内容的控制:

<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))); 
} 
+0

好的...但内容问题呢?毕竟这是一个该死的帆布......允许多个孩子! –

+0

@Zarathos:请检查更新。我没有测试过这个,但它应该像那样工作。 –

+0

画布坐在什么位置?它只是在窗户内吗?或者在另一个网格/画布内? Canvas不是一个内容控件,所以你不应该得到关于内容的错误,因为它没有内容属性。画布'容器可能是一个持有两件物品的内容控件。 – sircodesalot

2

添加到Daniel的回答,你必须明白,WPF引入了一个名为“依赖属性”和“依赖对象”的概念。简而言之,就像C#中的Objects可以具有属性一样,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功能,您至少需要了解它。

+1

'Canvas.Left'是附加属性,而不是依赖属性。 –

+0

正确,但附属属性* IS-A *依赖属性。你只需注册他们不同的方式:DependencyProperty.Register(普通)与DependencyProperty.RegisterAttached(附加) – sircodesalot

+1

确实。这个区别很重要。 –