简体   繁体   English

如何在WPF中将控件标记为“私有”?

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

With WinForms programs I've become accustomed to marking the Modifiers property of a control as 'Private' to prevent external classes and whatever else have you from being able to see and mess with them. 使用WinForms程序,我已经习惯于将控件的Modifiers属性标记为“Private”,以防止外部类和其他任何让你无法看到和搞乱它们的东西。

Being still very green with WPF, I see no obvious equivalent in WPF that allows me to make it so external classes cannot see a control I drop onto a form or another user control or what not. 仍然非常绿色的WPF,我发现在WPF中没有明显的等价物允许我这样做,所以外部类无法看到控件我放到表单或其他用户控件或什么不是。 I did notice something of x:FieldModifier = "Private" but I get the error "x:FieldModifier = "Private" is not valid for the language C#". 我注意到x的一些东西:FieldModifier =“Private”但我收到错误“x:FieldModifier =”Private“对于C#语言无效”。

How do I mark a control as Private so it cannot be viewed or accessed by external class objects? 如何将控件标记为“私有”,以便外部类对象无法查看或访问它?

TL;DR TL; DR

Most of the time you don't need to worry about this in WPF. 大多数情况下,您不需要在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. 如果使用x:Name属性命名XAML元素,则可以使用x:FieldModifier属性来控制表示该元素的自动生成字段的可见性。 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. 如果未命名XAML元素,则不要使用x:FieldModifier属性。

Read on for a more detailed explanation. 继续阅读以获得更详细的解释。


Explicit naming and generated fields 显式命名和生成的字段

If you create a new WPF application project in Visual Studio, it will create a MainWindow class, the XAML for which looks something like this: 如果在Visual Studio中创建一个新的WPF应用程序项目,它将创建一个MainWindow类,其XAML看起来像这样:

<Window x:Class="StackOverflow.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>

If you look at the code-behind class for this window, it will look like this: 如果你看一下这个窗口的代码隐藏类,它将如下所示:

// Several using statements...

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

Note the use of the partial keyword to denote this as a partial class. 请注意使用partial关键字将其表示为部分类。 If you navigate to the project's obj\\Debug folder using Windows Explorer, you will find a file called MainWindow.g.cs : it is this file that contains the code generated by the IDE from your XAML (it is basically the equivalent of the *.Designer.cs file from WinForms). 如果使用Windows资源管理器导航到项目的obj \\ Debug文件夹,您将找到一个名为MainWindow.g.cs的文件:这个文件包含IDE从XAML生成的代码(它基本上等同于*来自WinForms的.Designer.cs文件)。

Your window has a Grid on it, but note that it is not surfaced directly anywhere in the code for MainWindow . 您的窗口上有一个网格 ,但请注意,它不会直接显示在MainWindow代码的任何位置。 Now edit your XAML to give the Grid a name: 现在编辑你的XAML给Grid一个名字:

<Grid x:Name="_myGrid">

Compile the application, and open the MainWindow.g.cs file again. 编译应用程序,然后再次打开MainWindow.g.cs文件。 You will see that the following line has been added: 您将看到添加了以下行:

internal System.Windows.Controls.Grid _myGrid;

Setting the x:Name property of the element in the XAML has caused the code generator to add a field with that name. 在XAML中设置元素的x:Name属性导致代码生成器添加具有该名称的字段。 The field is marked as internal which means it is accessible to all types in your project, but not to any other projects that reference your project. 该字段标记为internal ,这意味着项目中的所有类型都可以访问该字段,但不能访问引用项目的任何其他项目。

So basically, if you do not explicitly name an element in the XAML using the x:Name attribute, the code generator will not create a named field for the element in the code-behind class, and your element will effectively be private (this means that the class itself cannot access the element directly either). 所以基本上,如果你没有使用x:Name属性在XAML中明确命名一个元素,代码生成器将不会为代码隐藏类中的元素创建一个命名字段,并且你的元素实际上是private (这意味着该类本身不能直接访问该元素)。


Nameless UI elements can still be accessed from code 仍然可以从代码访问无名UI元素

You should bear in mind however that, just because an element does not have a name does not mean it cannot be accessed via code. 但是,您应该记住,仅仅因为元素没有名称并不意味着它不能通过代码访问。 You can always "walk" the visual tree and access elements that way. 您始终可以“遍历”可视树并以这种方式访问​​元素。 For example, because the window's content is set to a single Grid element, you can access that grid through code like so: 例如,因为窗口的内容设置为单个Grid元素,所以您可以通过以下代码访问该网格:

Grid grid = (Grid) this.Content;

this refers to the MainWindow class instance. this指的是MainWindow类实例。

WinForms has exactly the same "problem" as WPF in this regard: even controls that are not explicitly named can still be accessed through code. 在这方面,WinForms与WPF具有完全相同的“问题”:即使是未明确命名的控件仍然可以通过代码访问。 Imagine a WinForms Form with a single Button control on it. 想象一下,WinForms 表单上有一个Button控件。 You can access that button like so: 您可以像这样访问该按钮:

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

The fact that the button had a default Modifiers value of "Private" did not stop the code from being able to access it. 按钮的默认修饰符值为“私有”这一事实并未阻止代码访问它。


The FieldModifier attribute controls generated field visibility FieldModifier属性控制生成的字段可见性

Coming back to WPF, particularly if you're using the Model-View-ViewModel (MVVM) pattern, you will rarely need to explicitly name your elements in the XAML, hence the default behaviour will be fine. 返回到WPF,特别是如果您使用的是Model-View-ViewModel(MVVM)模式,您很少需要在XAML中明确命名您的元素,因此默认行为就可以了。 However, if you do find that you need to name your XAML elements, and you wish to "hide" these elements, then you can use the x:FieldModifier attribute to set the visibility of an element to private instead of the default internal . 但是,如果您确实发现需要命名XAML元素,并且希望“隐藏”这些元素,则可以使用x:FieldModifier属性将元素的可见性设置为private而不是默认internal The value used for the attribute is language-dependent and case-sensitive, eg. 用于该属性的值是语言相关的并且区分大小写,例如。 for C#: 对于C#:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM