命名控件存在于 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 的子代,而是UserControlControlTemplate 的子代。 Windows 10 的行为完全符合其应有的方式,并且您似乎在 Windows 8 渲染引擎中发现了一个错误,如果它有效的话。

一个

有一些解决方法。第一种是将属性添加到UserControl 的教科书方法,该方法添加了对该控件的访问权限。因为您允许内容是动态的,所以该属性(或方法)内的操作也需要是动态的。 GetControl&lt;TextBlock&gt;("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 中处理TextBlock1Loaded 事件,并在处理程序方法中将一个字段设置为sender 的值。您甚至可以将其转换为TextBlock,以便输入所有内容。这使您可以轻松访问,但有时间的潜在缺点。如果您尝试在设置之前访问字段值,您可能会发现它为空。但是,在大多数情况下,这是最简单的。

所以,这是处理它的三种方法。我认为认识到这是预期行为非常重要,因为 XAML 元素只能有一个父元素,并且您正在通过 ContentPresenterContent 属性设置该父元素。话虽如此,这可能是预期的行为,但它显然不是直观的。

祝你好运。

【讨论】:

以上是关于命名控件存在于 Windows 10 但不存在于 Windows 8.1的主要内容,如果未能解决你的问题,请参考以下文章

Axios 拦截器令牌标头存在于配置中,但不存在于请求标头中

如何检查用户是不是存在于 LDAP 上

删除存在于另一个命名空间 rails 中的模型

SQL Server 查询。用户存在于另一个表中但不存在用户的位置

ValueError:`class_weight`必须包含数据中的所有类。类{1,2,3}存在于数据中,但不存在于`class_weight`中

如何将属性应用于存在但不立即可见的钛元素?