自定义WPF/XAML画布
本文关键字:画布 XAML WPF 自定义 | 更新日期: 2023-09-27 17:58:14
我正在尝试创建和使用自定义画布。这是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>
我得到两个不同的错误:
属性"Content"只能设置一次。===>它不是继承了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>
Left
和Top
是附加属性。这意味着它们不是由您的类继承的。
您需要更改用户控件声明以使用Canvas.Left
和Canvas.Top
:
<Namespace:MyUserControl Core:Name="Control2" Canvas.Left="744" Canvas.Top="42"
MyProperty="150"/>
内容的问题是您设置了两次,就像错误消息所说的那样。
- 在
MyCanvas.xaml
中将其设置为Image
- 使用它时,您将其设置为用户控件
要修复它,您需要向MyCanvas
添加一个ItemsControl
,并将其声明为表示内容的控件:
<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)));
}
在Daniel的回答中,您必须了解WPF引入了一个名为"依赖属性"answers"依赖对象"的概念。简而言之,就像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功能,您至少必须了解它。