[英]Using named in reusable WPF control
I recentrly discovered "reusable controls" in WPF and I have a project where they seem to provide me with a solution to a problem I have.我最近在 WPF 中发现了“可重复使用的控件”,我有一个项目,它们似乎为我提供了解决我遇到的问题的方法。
Let me sketch the situation: I need to make several UI elements.让我描述一下情况:我需要制作几个 UI 元素。 All of them share a common base, a common style/layout/template let's say, and they also share some common logic.
它们都共享一个共同的基础,可以说是一个共同的样式/布局/模板,并且它们还共享一些共同的逻辑。
Next to that, all of these elements have some element-specific stuff.除此之外,所有这些元素都有一些特定于元素的东西。
You could say that I have some kind of inheritance here, but then for both XAML and CS.你可以说我这里有某种 inheritance,但是对于 XAML 和 CS。
The way I wanted to solve this, was by making an outer reusable element, I made a small example.我想解决这个问题的方法是制作一个外部可重用元素,我做了一个小例子。 The common part Is the
Title
label and the border.公共部分是
Title
label 和边框。 The element-specific UI can then be inserted into UserContent
.然后可以将特定于元素的 UI 插入到
UserContent
中。
The code looks something like this (although it's simplified for the sake of brevity and conciseness, I also have an eventhandler and a routed event in my actual application):代码看起来像这样(尽管为了简洁起见进行了简化,但我在实际应用程序中也有一个事件处理程序和一个路由事件):
ReusableControl.xaml ReusableControl.xaml
<UserControl x:Class="StackOverflowQuestion4.ReusableControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root">
<Border BorderBrush="Black"
BorderThickness="1"
Width="400"
Height="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Content="{Binding Title, ElementName=root}"
Grid.Row="0"/>
<ContentControl Content="{Binding UserContent, ElementName=root}"
Grid.Row="1"/>
</Grid>
</Border>
</UserControl>
ReusableControl.xaml.cs ReusableControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace StackOverflowQuestion4
{
public partial class ReusableControl : UserControl
{
public ReusableControl()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ReusableControl), new PropertyMetadata(string.Empty));
public object UserContent
{
get { return GetValue(UserContentProperty); }
set { SetValue(UserContentProperty, value); }
}
public static readonly DependencyProperty UserContentProperty =
DependencyProperty.Register("UserContent", typeof(object), typeof(ReusableControl), new PropertyMetadata(string.Empty));
}
}
Lovely, I can now use my special control in other parts of my code, and I can insert whatever I want into the UserContent
field.太棒了,我现在可以在代码的其他部分使用我的特殊控件,并且可以将我想要的任何内容插入到
UserContent
字段中。
MainWindow.xaml主窗口.xaml
<Window x:Class="StackOverflowQuestion4.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:StackOverflowQuestion4"
mc:Ignorable="d"
Title="MainWindow"
SizeToContent="WidthAndHeight">
<Grid Width="800"
Height="600">
<local:ReusableControl Title="Test">
<local:ReusableControl.UserContent>
<Rectangle Width="300"
Height="100"
Fill="Blue"/>
</local:ReusableControl.UserContent>
</local:ReusableControl>
</Grid>
</Window>
This works great, but the problem arises when I start to name things.这很好用,但是当我开始给事物命名时,问题就出现了。 Simply adding a name to an element inside of my
ReusableControl
causes a compilation error.简单地向
ReusableControl
中的元素添加名称会导致编译错误。
<Rectangle Width="300"
Height="100"
Fill="Blue"
Name="LolWhatAmIDoing"/>
I get the following error:我收到以下错误:
MC3093 - Cannot set Name attribute value 'LolWhatAmIDoing' on element 'Rectangle'.
MC3093 - 无法在元素“矩形”上设置名称属性值“LolWhatAmIDoing”。 'Rectangle' is under the scope of element 'ReusableControl', which already had a name registered when it was defined in another scope.
'Rectangle' 在元素 'ReusableControl' 的 scope 下,它在另一个 scope 中定义时已经注册了名称。
This seems like such a small issue, but I cannot find an easy solution to this problem.这似乎是一个小问题,但我找不到解决这个问题的简单方法。
I found this thread on the forum, but it does not really provide a solution.我在论坛上找到了这个帖子,但它并没有真正提供解决方案。 Since I'm pretty new to all of this, I also don't really get what the issue is, so apologies if I'm slow minded.
由于我对所有这一切都很陌生,所以我也不太明白问题是什么,所以如果我反应迟钝,我深表歉意。
Should I move to CustomControls?我应该转到 CustomControls 吗?
What you show is a simple property assignment: you set the value of type Rectangle
to the property ReusableControl.UserContent
.您显示的是一个简单的属性分配:您将
Rectangle
类型的值设置为属性ReusableControl.UserContent
。 It's important to understand that the Rectangle
is not part of the visual tree at this point.重要的是要了解
Rectangle
此时不是可视化树的一部分。 It's a simple property value that is only accessible via the property and not via the visual tree.这是一个简单的属性值,只能通过属性访问,而不能通过可视化树访问。
This all happens in the scope of MainWindow
.这一切都发生在
MainWindow
的 scope 中。
But the Rectangle
is not a member of this scope. The ReusableControl
is adding it to its own visual subtree or scope by binding the value of ReusableControl.UserContent
to a ContentControl
.但是
Rectangle
不是这个 scope 的成员。 ReusableControl
通过将ReusableControl.UserContent
的值绑定到ContentControl
来将它添加到自己的可视子树或 scope 中。 This is were the Rectangle
exists ie is rendered in the visual tree.这是
Rectangle
存在的情况,即在可视化树中呈现。
It effectively doesn't exist in the scope of MainWindow
.它实际上不存在于
MainWindow
的 scope 中。 It effectively only exists inside the ReusableControl
in the "shape" of a ContentControl
.它实际上仅存在于
ContentControl
的“形状”中的ReusableControl
内部。 This means that the scope of ReusableControl
is the only name scope where you can register a name for child elements.这意味着
ReusableControl
的 scope 是唯一可以为子元素注册名称的名称 scope。 It's also the only scope where you can directly reference it (if it had been defined and registered in this scope).它也是唯一可以直接引用它的 scope(如果它已在此范围内定义和注册)。
If you understand this, then you understand that the Rectangle
is currently trying to register a name in the wrong scope, a scope in which it doesn't exist.如果你明白这一点,那么你就明白了
Rectangle
当前正在尝试在错误的 scope 中注册一个名称,一个它不存在的 scope。
As a consequence, you cannot directly refer to it in the scope of MainWindow
.因此,您不能在
MainWindow
的 scope 中直接引用它。 You would have to dig into the ContentTemplate
of the UserControl
(which is a ContentControl
) in order to get the nested ContentControl
that actually hosts the Rectangle
.您必须深入研究
UserControl
的ContentTemplate
(这是一个ContentControl
)才能获得实际承载Rectangle
的嵌套ContentControl
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.