2013-02-07 77 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

確實。這個區別很重要。 –