XAML控件不可访问,它具有一定的保护级别
其它namespace的代码访问控件时会出现这个问题
需要把控件状态由protected改为public
<TextBlock x:FieldModifier="public" x:Name="AccessibleTextBlock" />
The x:Name attribute in XAML creates named fields that you can use to access the controls from the code-behind. However, as opposed to WPF, in UWP these fields are private which means you can access them from the code-behind only, not from other classes. While noting it is a good idea from architectural standpoint, is it possible to change this behavior?
Normal behavior
Let’s define a simple TextBlock
control in XAML.
1
|
<TextBlock x:Name="InaccessibleTextBlock" />
|
Now, what happens if we create a new class that takes the page as parameter of one of the methods and tries to access the TextBlock
?
1
2
3
4
5
6
7
|
public static class OutsideAccess
{
public static void ChangeTexts(MainPage page)
{
page.InaccessibleTextBlock.Text = "Accessed"; //does not work!
}
}
|
The app will not compile, because the field is inaccessible due to its protection level.
To see what actually happens behind the scenes, let’s open the auto-generated MainPage.g.i.cs file which can be found in the obj folder. We can find the following field there:
1
2
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 14.0.0.0")]
private global::Windows.UI.Xaml.Controls.TextBlock InaccessibleTextBlock;
|
Clearly, the field is defined as private.
x:FieldModifier directive
To change the code generation behavior, you can use the x:FieldModifier
directive. This allows you to specify excatly which access modifier should be field have.
1
|
<TextBlock x:FieldModifier="public" x:Name="AccessibleTextBlock" />
|
Now, accessing the field from the outside works as a charm:
1
2
3
4
5
6
7
|
public static class OutsideAccess
{
public static void ChangeTexts(MainPage page)
{
page.AccessibleTextBlock.Text = "Accessed";
}
}
|
Note that you are not limited to public
and private
only, and you can also set the field to be internal
or protected
.
We can confirm the change of visiblity was reflected in the generated source code:
1
2
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 14.0.0.0")]
public global::Windows.UI.Xaml.Controls.TextBlock AccessibleTextBlock;
|
WPF
If you wonder, what is the default behavior in WPF, wonder no more!
WPF’s convention is to set all named fields as internal
by default:
1
2
|
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock InaccessibleTextBlock;
|
You can use the x:FieldModifier
directive to modify the visibility the same way as in UWP.