命名控件存在于 Windows 10 但不存在于 Windows 8.1
Posted
技术标签:
【中文标题】命名控件存在于 Windows 10 但不存在于 Windows 8.1【英文标题】:Named control exists on Windows 10 but not on Windows 8.1 【发布时间】:2018-06-29 08:50:34 【问题描述】:我在 Windows 8.1 应用商店应用中有以下代码。此代码在 Windows 10 上运行良好,但在 Windows 8.1 上崩溃。 MainPage.xaml.cs 中的第二个命名控件在 Win 8.1 上为空,但在 Windows 10 上不为空。这不是时间问题,因为在页面加载后的任何后续事件处理程序中仍不会填充命名控件。这到底是怎么回事?
总而言之,我有一个 ContentControl,其模板中定义了一个 ContentPresenter。然后在页面上实例化该 ContentControl,并使用命名的子控件(使用“x:Name”)作为其内容。在 Windows 10 上,该命名控件存在于代码隐藏中。在 Windows 8.1 上它是 null
MyUserControl1.xaml
<ContentControl
x:Class="App1.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<ContentControl.Template>
<ControlTemplate>
<ContentPresenter Content="Binding Content, RelativeSource=RelativeSource TemplatedParent" />
</ControlTemplate>
</ContentControl.Template>
MainPage.xaml
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="ThemeResource ApplicationPageBackgroundThemeBrush">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="TextBlock1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextAlignment="Center"
FontSize="50"
TextWrapping="Wrap" />
<local:MyUserControl1 Grid.Column="1">
<TextBlock x:Name="TextBlock2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextAlignment="Center"
FontSize="50"
TextWrapping="Wrap" />
</local:MyUserControl1>
</Grid>
MainPage.xaml.cs
using Windows.UI.Xaml.Controls;
namespace App1
public sealed partial class MainPage : Page
public MainPage()
this.InitializeComponent();
TextBlock1.Text = "This works";
TextBlock2.Text = "This does not work because TextBlock2 is null";
【问题讨论】:
【参考方案1】:当然你不能引用这个。您的 TextBlock2
被您明确设置为 另一个 控件的内容,基本上超出了范围。渲染完成后,您的TextBlock2
不再是MainPage
的子代,而是UserControl
中ControlTemplate
的子代。 Windows 10 的行为完全符合其应有的方式,并且您似乎在 Windows 8 渲染引擎中发现了一个错误,如果它有效的话。
一个
有一些解决方法。第一种是将属性添加到UserControl
的教科书方法,该方法添加了对该控件的访问权限。因为您允许内容是动态的,所以该属性(或方法)内的操作也需要是动态的。 GetControl<TextBlock>("TextBlock1")
之类的东西可以找到你。
public bool TryGetControl<T>(string name, out T control)
try
var children = RecurseChildren(this.MyUserControl);
control = children
.Where(x => Equals(x.Name, name))
.OfType<T>()
.First();
return true;
catch
control = default(T);
return false;
public List<Control> RecurseChildren(DependencyObject parent)
var list = new List<Control>();
var count = VisualTreeHelper.GetChildrenCount(parent);
var children = Enumerable.Range(0, count - 1)
.Select(x => VisualTreeHelper.GetChild(parent, x));
list.AddRange(children.OfType<Control>());
foreach (var child in children)
list.AddRange(RecurseChildren(child));
return list;
两个
您可以做的第二件事就是从页面本身通过UserControl
的子层次结构寻找控件。逻辑将与第一个(上图)相同,但它将在页面内执行,而不是您的 UserControl
逻辑的一部分。当您出于某种原因需要在ListView
中找到ScrollViewer
或者在Button
中查找内部Border
时,您已经做了这种事情。
原来我已经在一篇博文中解释了这一点,你可以作为参考:http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html
三个
这是第三种,也许是最简单的方法。在您的MainPage
中处理TextBlock1
的Loaded
事件,并在处理程序方法中将一个字段设置为sender
的值。您甚至可以将其转换为TextBlock
,以便输入所有内容。这使您可以轻松访问,但有时间的潜在缺点。如果您尝试在设置之前访问字段值,您可能会发现它为空。但是,在大多数情况下,这是最简单的。
所以,这是处理它的三种方法。我认为认识到这是预期行为非常重要,因为 XAML 元素只能有一个父元素,并且您正在通过 ContentPresenter
的 Content
属性设置该父元素。话虽如此,这可能是预期的行为,但它显然不是直观的。
祝你好运。
【讨论】:
以上是关于命名控件存在于 Windows 10 但不存在于 Windows 8.1的主要内容,如果未能解决你的问题,请参考以下文章
Axios 拦截器令牌标头存在于配置中,但不存在于请求标头中
SQL Server 查询。用户存在于另一个表中但不存在用户的位置
ValueError:`class_weight`必须包含数据中的所有类。类{1,2,3}存在于数据中,但不存在于`class_weight`中