我的项目中有一些用户控件,如pnlCanvas和pnlTools。
- pnlTools**中有几个按钮,如"添加圆"、"添加矩形"、"添加文本"等。
当用户单击其中一个按钮时,应将元素添加到位于pnlCanvas中的Canvas(cnvsObjects)的子项。
我的***MainWindow.xaml***是这样的:
<Window x:Class=...>
<Grid>
...
<local:pnlCanvas Grid.Column="2"/>
<GridSplitter Grid.Column="3" HorizontalAlignment="Stretch"/>
<local:pnlTools Grid.Column="4" />
...
</Grid>
</Window>
如果您的计算机上有一个
<UserControl x:Class=...>
<GroupBox>
<GroupBox.Header...>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="cnvsObjects" Width="1920" Height=...>
</Canvas>
</ScrollViewer>
</GroupBox>
</UserControl>
***pnlTools.xaml***文件名:
<UserControl x:Class=...>
<GroupBox>
<GroupBox.Header...>
<StackPanel>
<Button Content="Add Text" Click="Button_Click"></Button>
<Button Content="Add Rectangle"></Button>
<Button Content="Add Line"></Button>
...
</StackPanel>
</GroupBox>
</UserControl>
如果您的计算机上有一个
....
public partial class pnlTools : UserControl
{
public pnlTools()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TextBlock tb = new TextBlock();
tb.TextWrapping = TextWrapping.Wrap;
tb.Margin = new Thickness(10);
tb.Text = "A Text as Test";
cnvsObjects.Children.Add(tb); // Error!
}
}
}
正如我所搜索的,我知道在这种情况下我应该使用像Dependency Properties这样的东西。如果它是一个TextBlock,我可以使用Data Binding和Dependency Property。但它不是一个Property,而是一个Method(Children. Add)。
我是WPF的新手,所以如果所有的东西都在 * MainWindow. xaml * 中,我就没有问题了。我已经将 * MainWindos. xaml * 分成了一些UserControl(嵌套)来降低复杂性并避免文件变得巨大。我选择UserControl是为了这个目的吗?还是我应该使用其他东西?这样做的最好方法是什么?
很抱歉,这篇文章太长了。我不能分析与这个问题相关的其他问题和答案,因为它们对我来说太复杂了。谢谢。
2条答案
按热度按时间gudnpqoy1#
You are executing the
Button.Click
event handlers in the wrong context. You would have to handle theButton.Click
event in a context that has access to thepnlCanvas
control, if this makes sense. Based on your posted example, the correct context would be theMainWindow
as it hosts bothpnlCanvas
andpnlTools
.The recommended solution would be to change your overall design. This would involve the introduction of data model classes, that represent/hold the data for a
UIElement
, that you wish to add to the Canvas.Such data would include the position on the canvas (x/y coordinates) and some data to display e.g., a text.
You would add those data models to a collection that serves as a binding source for a
ListBox
. TheCanvas
itself would be the panel of theListBox
, by assigning it to theListBox.ItemsPanel
property. You then define aDataTemplate
for each data model type, where theDataTemplate
contains the actual control you want to show. See Microsoft Docs: Data Templating Overview to learn aboutDataTemplate
.However, to fix your example you must first let the
PnlCanvas
control expose a public method that allows external controlslike theMainWindow
to add elements to its internalCanvas
(note that the proper naming for classes in C# would use PascalCasing. For examplepnlTools
should bePnlTools
. See Microsoft Docs: Naming Guidelines. All provided code examples will use the official C# naming convention):Next, let
PnlCanvas
expose a set of routed commands, that the buttons in thePnlTools
control can use. TheMainWindow
will then listen to those commands. See Microsoft Docs: Commanding OverviewThe complete
PnlCanvas
class will then look as follows (example only shows adding text to theCanvas
or any otherPanel
):PnlCanvas.xaml.cs
Then let
PnlTools
use the routed commands defined inPnlCanvas
:PnlTools.xaml
Finally, let
MainWindow
execute the command:MainWindow.xaml.cs
pxy2qtax2#
使用
UserControl
的基本思想有两点:1.保持代码更易读、更有组织、更易于维护和长期扩展。
1.避免冗余代码和重复的代码块。当应用程序在不同的窗口或页面中使用相似的UI模式时,设计一个
UserControl
并在需要的任何地方使用它是一个很好的实践。回到您的主要问题,您可以在PnlTools代码隐藏中定义一个委托/事件,并在MainWindow代码隐藏中向其注册一个事件侦听器。