如何在 WPF 中将控件标记为 'Private'?

How do I mark a control as 'Private' in WPF?

对于 WinForms 程序,我已经习惯于将控件的修饰符 属性 标记为 'Private' 以防止外部 classes 以及您能够看到的任何其他内容和他们打交道。

WPF 仍然非常新,我在 WPF 中看不到明显的等价物,可以让我在外部 classes 看不到我放在窗体或其他用户控件上的控件或其他控件。我确实注意到 x:FieldModifier = "Private" 但我收到错误消息“x:FieldModifier = "Private" 对 C# 语言无效”。

如何将控件标记为私有,使其无法被外部 class 对象查看或访问?

TL;DR

Most of the time you don't need to worry about this in WPF. However:

  • If you name a XAML element using the x:Name attribute, then you can use the x:FieldModifier attribute to control the visibility of the auto-generated field representing that element. This attribute value is language- and case-specific.
  • If you don't name a XAML element, then don't bother using the x:FieldModifier attribute.

Read on for a more detailed explanation.


显式命名和生成的字段

如果您在 Visual Studio 中创建一个新的 WPF 应用程序项目,它将创建一个 MainWindow class,XAML 看起来像这样:

<Window x:Class="Whosebug.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>

    </Grid>
</Window>

如果您查看此 window 的代码隐藏 class,它将如下所示:

// Several using statements...

namespace Whosebug
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

请注意使用 partial 关键字将其表示为部分 class。如果您使用 Windows 资源管理器导航到项目的 obj\Debug 文件夹,您将找到一个名为 MainWindow.g.cs[=75= 的文件]:这个文件包含 IDE 从您的 XAML 生成的代码(它基本上等同于 *.Designer.cs来自 WinForms 的文件)。

您的 window 上面有一个 Grid,但请注意它不会直接出现在 Main[=107= 的代码中的任何地方]。现在编辑 XAML 为 Grid 命名:

<Grid x:Name="_myGrid">

编译应用程序,并再次打开MainWindow.g.cs文件。您会看到添加了以下行:

internal System.Windows.Controls.Grid _myGrid;

设置 XAML 中元素的 x:Name 属性 导致代码生成器添加具有该名称的字段。该字段标记为 internal,这意味着它可供您项目中的所有类型访问,但不能供引用您项目的任何其他项目访问。

所以基本上,如果您没有使用 x:Name 属性显式命名 XAML 中的元素,代码生成器将不会为代码隐藏 class 中的元素,您的元素实际上将是 private(这意味着 class 本身也无法直接访问该元素)。


仍然可以从代码访问无名 UI 元素(如果您有实例)

通过“遍历”Window 实例的可视化树,仍然可以通过代码访问没有名称的元素。例如,因为 window 的内容设置为单个 Grid 元素,您可以通过如下代码访问该网格:

Grid grid = (Grid) this.Content;
这里的

this指的是MainWindowclass实例。

WinForms 在这方面与 WPF 有着完全相同的“问题”:即使是未明确命名的控件仍然可以通过代码访问。想象一个带有单个 Button 控件的 WinForms Form。您可以像这样访问该按钮:

Button button = (Button) this.Controls[0];

按钮的默认 Modifiers 值“Private”并没有阻止代码访问它。


FieldModifier 属性控制生成的字段可见性

回到 WPF,特别是如果您使用模型-视图-视图模型 (MVVM) 模式,您将很少需要在 XAML 中显式命名您的元素,因此默认行为将是美好的。但是,如果您确实发现需要命名 XAML 元素,并且希望“隐藏”这些元素,则可以使用 x:FieldModifier 属性来设置元素的可见性为 private 而不是默认的 internal。用于该属性的值取决于语言并且区分大小写,例如。对于 C#:

<Grid x:Name="_myGrid" x:FieldModifier="private">