【发布时间】:2017-07-21 07:43:08
【问题描述】:
我是使用 WPF 的新手,但非常喜欢在 xaml 中编写视图代码并在视图模型中支持代码的想法。我想做的是通过将 Canvas 与状态栏相关联来扩展 Canvas 的使用,该状态栏根据 Canvas 的内容和鼠标位置显示状态文本(下面的程式化代码不包括此)。
按照https://www.codeproject.com/Articles/82464/How-to-Embed-Arbitrary-Content-in-a-WPF-Control,我的方法是创建一个包含 Canvas 的 UserControl 并在其中放置一个 ContentPresenter。
我有两个问题要解决: 1) 我需要做什么才能允许多个子控件,就像 Canvas 允许多个子控件一样? 2) 如何从主窗口代码中访问 Canvas.Left 等 Canvas 的属性?
提前感谢您提出的任何建议。
UserControl xaml 代码、UserControl 后面代码、主窗口 xaml 代码:
<UserControl x:Class="SO.CanvasUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SO"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Template>
<ControlTemplate TargetType="{x:Type local:CanvasUserControl}">
<Canvas Width="200" Height="100" Background="Green">
<ContentPresenter/>
</Canvas>
</ControlTemplate>
</UserControl.Template>
</UserControl>
后面的代码:
public partial class CanvasUserControl : UserControl
{
public CanvasUserControl()
{
InitializeComponent();
}
}
主窗口:
<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SO"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<!-- works as expected
<Canvas Width="200" Height="100" Background="Green">
<Line X1="0" Y1="0" X2="200" Y2="100" Stroke="Red"/>
<Line X1="200" Y1="0" X2="0" Y2="100" Stroke="Red"/>
</Canvas>
-->
<!-- works as expected
<Canvas Width="200" Height="100" Background="Green" x:Name="MyCanvas">
<Line X1="{Binding ElementName=MyCanvas, Path=Left}" Y1="{Binding ElementName=MyCanvas, Path=Top}" X2="{Binding ElementName=MyCanvas, Path=ActualWidth}" Y2="{Binding ElementName=MyCanvas, Path=ActualHeight}" Stroke="Red"/>
<Line X1="{Binding ElementName=MyCanvas, Path=ActualWidth}" Y1="{Binding ElementName=MyCanvas, Path=Top}" X2="{Binding ElementName=MyCanvas, Path=Left}" Y2="{Binding ElementName=MyCanvas, Path=ActualHeight}" Stroke="Red"/>
</Canvas>
-->
<!-- How do I add more than one child control as nested content for the Canvas?
<local:CanvasUserControl x:Name="MyCanvasUserControl">
<Line X1="0" Y1="0" X2="200" Y2="100" Stroke="Red"/>
<Line X1="200" Y1="0" X2="0" Y2="100" Stroke="Green"/>
</local:CanvasUserControl>
-->
<!-- How do I access dependency properties of the Canvas?
<local:CanvasUserControl x:Name="MyCanvasUserControl">
<Line X1="{Binding ElementName=MyCanvasUserControl, Path=Left}" Y1="{Binding ElementName=MyCanvasUserControl, Path=Top}" X2="{Binding ElementName=MyCanvasUserControl, Path=ActualWidth}" Y2="{Binding ElementName=MyCanvasUserControl, Path=ActualHeight}" Stroke="Red"/>
</local:CanvasUserControl>
-->
</Grid>
</Window>
【问题讨论】:
-
A
UserControl继承自ContentControl。它有一个Content属性,类型为Object。我不确定您在这里真正想要的是UserControl。您是否只是希望能够将 Canvas 的一堆属性汇总到某种包中,然后一起重用它们?这可以很容易地完成,但我会用 Style 来代替。 -
我想做的是创建一个可重复使用的控件,它的作用类似于 Canvas,但它下面还有一个 StatusBar。我打算在其中使用它的每个项目都会在其“Canvas Children”列表中显示它想要的任何内容,例如两条对角线。事实上,我已经让所有这些代码工作了,但是厌倦了复制粘贴 20-30 行的 xaml 以及消耗鼠标位置并返回状态栏文本的 ViewModel 代码。从我对 StackOverflow 以及其他网站的背景阅读来看,UserControl 似乎是要走的路。
-
定义“随心所欲”。
-
如果你只想在没有任何额外 XAML 噪音的情况下加入随机的东西,你需要一个
ItemsControl的子类,它有一个Canvas和一个ItemsPanel。如果要为其添加状态栏,则需要将控件的Template替换为添加状态栏的内容。到目前为止,所有这些都可以在 Style 中完成,甚至无需编写自己的子类。编写自己的子类的唯一原因是向消费者公开Canvas的属性(例如,添加Line对象的MainWIndow中的XAML)。你必须给你的子类一个依赖... -
我认为 ItemsControl 是要走的路。不幸的是,我向你扔了一堆关于模板和项目面板的伊特鲁里亚象形文字,现在我必须在几分钟内回家。 Here's an answer that's very close to your case,不过;
Template将用于显示您的控件。
标签: wpf