【问题标题】:x:Name doesn't work in XAML Flyout controlx:Name 在 XAML Flyout 控件中不起作用
【发布时间】:2014-12-11 01:40:55
【问题描述】:

我在 Windows 8.1 C# 应用程序中尝试了以下操作:

<!-- XAML file -->
<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton Label="Add News Feed" Icon="Add">
            <AppBarButton.Flyout>
                <Flyout>
                    <StackPanel Width="400">
                        <TextBlock TextWrapping="Wrap" Text="Enter Text:" Margin="0,0,0,10"/>
                        <TextBox x:Name="inputTextBox"/>
                        <Button Content="Add" HorizontalAlignment="Right" VerticalAlignment="Stretch" Click="AddButton_Click"/>
                    </StackPanel>
                </Flyout>
            </AppBarButton.Flyout>
        </AppBarButton>
    </CommandBar>
</Page.BottomAppBar>
// C# file
private void AddButon_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    var text = inputTextBox.Text;
    // Do something with the text
}

但是,当我运行我的应用程序并单击“添加”按钮时,我得到一个 System.NullReferenceException,因为成员 inputTextBox 为空。我查了一下,生成的 InitializeComponent 方法有以下一行:

inputTextBox = (global::Windows.UI.Xaml.Controls.TextBox)this.FindName("inputTextBox");

我什至尝试将我的事件处理程序更改为调用 FindName,以防在显示 Flyout 时创建控件并且它仍然返回 null。为什么 FindName 找不到我的文本框?

更新:解决方法

我能够使用 VisualTreeHelper 访问 TextBox,如下所示:

TextBox textBox = null;
var parent = VisualTreeHelper.GetParent(sender as Button);
var numChildren = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < numChildren; ++i)
{
    var child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
    if (child != null && child.Name == "inputTextBox")
    {
        // Found the text box!
        textBox = child as TextBox;
        break;
    }
}

if (textBox != null)
{
    var text = textBox.Text;
    // Do something with the text
}

如果这确实被确认为 Windows 8.1 预览版中的错误,我将继续并关闭此问题。

【问题讨论】:

    标签: winrt-xaml windows-8.1


    【解决方案1】:

    这是 8.1 预览版的问题,我们希望在 8.1 的最终版本中解决此问题

    【讨论】:

    • 我想出使用 VisualTreeHelper 来查找文本框。我将在我的问题的更新中发布解决方法。
    • @Skippy - 我知道这一点,因为我在产品团队。
    • @JoeStegman 即使在发布后我仍然看到这个问题。解决了吗?
    【解决方案2】:

    如果您不想使用 VisualTreeHelper 方法,您也可以创建一个 Flyout 的子类,然后使用 Flyoutbase.SetAttachedFlyout(UIElement, FlyoutSubclass); 将其附加到您的 UI 元素上;

    class ForgotPasswordFlyout : Flyout
    {
        StackPanel contentPanel = new StackPanel();
        public Thickness margins = new Thickness(0, 0, 0, 10);
    
        public Button forgotPasswordButton;
        public ProgressBar forgotPasswordProgressBar;
        public TextBlock forgotPasswordMessageTextBlock;
        public TextBox forgotPasswordTextBox;
    
        public ForgotPasswordFlyout()
        {
            forgotPasswordMessageTextBlock = new TextBlock();
            forgotPasswordMessageTextBlock.Text = "Enter the email address you used to register.";
            forgotPasswordMessageTextBlock.Margin = margins;
            contentPanel.Children.Add(forgotPasswordMessageTextBlock);
    
            forgotPasswordTextBox = new TextBox();
            forgotPasswordTextBox.PlaceholderText = "Email";
            forgotPasswordTextBox.Margin = margins;
            contentPanel.Children.Add(forgotPasswordTextBox);
    
            forgotPasswordButton = new Button();
            forgotPasswordButton.Content = "Recover Password";
            contentPanel.Children.Add(forgotPasswordButton);
    
            forgotPasswordProgressBar = new ProgressBar();
            forgotPasswordProgressBar.IsIndeterminate = true;
            forgotPasswordProgressBar.Visibility = Visibility.Collapsed;
            contentPanel.Children.Add(forgotPasswordProgressBar);
    
            this.Content = contentPanel;
        }
    }
    

    现在,我们无法直接访问文本框,因为 x:Name 不起作用。但是,在视图控制器中,我们可以为这些 UI 元素注册事件。

    private void RecoverPasswordCommandButton_Click(object sender, RoutedEventArgs e)
        {
            ForgotPasswordFlyout forgotPassFlyout = new ForgotPasswordFlyout();
            forgotPassFlyout.forgotPasswordTextBox.TextChanged += forgotPasswordTextBox_TextChanged;
            forgotPassFlyout.forgotPasswordButton.Click += forgotPasswordFlyoutButton_Click;
            FlyoutBase.SetAttachedFlyout(RecoverPasswordCommandButton, forgotPassFlyout);
            FlyoutBase.ShowAttachedFlyout(RecoverPasswordCommandButton);
        }
    

    这样我们可以在事件触发时直接访问文本框并保存文本以供使用。

    void forgotPasswordTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox forgotPasswordTextBox = sender as TextBox;
            ForgotPasswordFlyout.forgotPasswordEmail = forgotPasswordTextBox.Text;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      • 2016-08-08
      • 1970-01-01
      相关资源
      最近更新 更多