[英]Using named in reusable WPF control
我最近在 WPF 中發現了“可重復使用的控件”,我有一個項目,它們似乎為我提供了解決我遇到的問題的方法。
讓我描述一下情況:我需要制作幾個 UI 元素。 它們都共享一個共同的基礎,可以說是一個共同的樣式/布局/模板,並且它們還共享一些共同的邏輯。
除此之外,所有這些元素都有一些特定於元素的東西。
你可以說我這里有某種 inheritance,但是對於 XAML 和 CS。
我想解決這個問題的方法是制作一個外部可重用元素,我做了一個小例子。 公共部分是Title
label 和邊框。 然后可以將特定於元素的 UI 插入到UserContent
中。
代碼看起來像這樣(盡管為了簡潔起見進行了簡化,但我在實際應用程序中也有一個事件處理程序和一個路由事件):
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
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));
}
}
太棒了,我現在可以在代碼的其他部分使用我的特殊控件,並且可以將我想要的任何內容插入到UserContent
字段中。
主窗口.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>
這很好用,但是當我開始給事物命名時,問題就出現了。 簡單地向ReusableControl
中的元素添加名稱會導致編譯錯誤。
<Rectangle Width="300"
Height="100"
Fill="Blue"
Name="LolWhatAmIDoing"/>
我收到以下錯誤:
MC3093 - 無法在元素“矩形”上設置名稱屬性值“LolWhatAmIDoing”。 'Rectangle' 在元素 'ReusableControl' 的 scope 下,它在另一個 scope 中定義時已經注冊了名稱。
這似乎是一個小問題,但我找不到解決這個問題的簡單方法。
我在論壇上找到了這個帖子,但它並沒有真正提供解決方案。 由於我對所有這一切都很陌生,所以我也不太明白問題是什么,所以如果我反應遲鈍,我深表歉意。
我應該轉到 CustomControls 嗎?
您顯示的是一個簡單的屬性分配:您將Rectangle
類型的值設置為屬性ReusableControl.UserContent
。 重要的是要了解Rectangle
此時不是可視化樹的一部分。 這是一個簡單的屬性值,只能通過屬性訪問,而不能通過可視化樹訪問。
這一切都發生在MainWindow
的 scope 中。
但是Rectangle
不是這個 scope 的成員。 ReusableControl
通過將ReusableControl.UserContent
的值綁定到ContentControl
來將它添加到自己的可視子樹或 scope 中。 這是Rectangle
存在的情況,即在可視化樹中呈現。
它實際上不存在於MainWindow
的 scope 中。 它實際上僅存在於ContentControl
的“形狀”中的ReusableControl
內部。 這意味着ReusableControl
的 scope 是唯一可以為子元素注冊名稱的名稱 scope。 它也是唯一可以直接引用它的 scope(如果它已在此范圍內定義和注冊)。
如果你明白這一點,那么你就明白了Rectangle
當前正在嘗試在錯誤的 scope 中注冊一個名稱,一個它不存在的 scope。
因此,您不能在MainWindow
的 scope 中直接引用它。 您必須深入研究UserControl
的ContentTemplate
(這是一個ContentControl
)才能獲得實際承載Rectangle
的嵌套ContentControl
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.