簡體   English   中英

在可重用的 WPF 控件中使用 named

[英]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 中直接引用它。 您必須深入研究UserControlContentTemplate (這是一個ContentControl )才能獲得實際承載Rectangle的嵌套ContentControl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM