如何在 XAML Metro 应用程序中禁用网格(面板)?

问题描述 投票:0回答:3

我想在 XAML Metro 应用程序中模拟模式对话框。

所以我打算在所有控件上设置 .IsEnabled = false,除了将作为模式对话框的控件之外。

显然 IsEnabled 不在 Grid 中,不在 Panel 中,不在 FrameworkElement 中。 如何禁用它而不使其成为用户控件?

我猜辛诺夫斯基走了很多弯路,现在整个东西更像是埃舍尔楼梯。我正在失去信心。请帮忙

c# xaml windows-8 windows-runtime
3个回答
2
投票

抱歉,我来晚了一点......

以下是我创建模式弹出窗口的方法 - 我使用了一个弹出对话框,其中顶部和底部部分是透明的,因此其后面的任何内容都会显示出来。当弹出窗口打开时,我将其大小设置为覆盖整个屏幕。

弹出窗口的顶部和底部部分也设置为自动调整大小(高度 = *),以便它们填满屏幕的整个顶部和底部。这可以防止任何输入进入下面的网格。

这是我在 Visual Studio 中弹出窗口的屏幕截图: enter image description here

弹出窗口是一个有 5 行的网格,其中 3 行用于对话框本身,2 行用于透明顶部和底部。

这是弹出窗口在我的应用程序中的外观。显然,网格通过透明的顶部和底部显示出来。由于弹出窗口填满整个屏幕,因此任何输入(键盘或鼠标)都会进入它而不是下面的网格,从而使弹出窗口充当模式对话框。

Popup with grid underneath

请注意,使用此策略,您必须处理以下事件:

  • 屏幕调整大小(全屏、快照视图、填充视图) - 您需要调整弹出窗口的大小以适合每个视图状态
  • 屏幕旋转 - 同样,您必须在这里处理调整大小
  • 键盘弹出窗口 - 您需要移动弹出窗口,以便屏幕键盘不会干扰它。

2
投票

在背景内容上设置

IsHitTestVisible = false

此外,您可以将焦点设置到模态层根目录中的某些内容,并将模态层根目录上的

TabNavigation
设置为
Cycle
,以确保用户无法通过 Tab/Shift+Tab 键退出它。还要确保模态层全部命中测试实体 - 例如
Transparent
或有其他填充,因此用户无法点击它。

还要确保当模态层可见时不会显示

Popups

示例:

<Grid>
    <StackPanel
        x:Name="BackgroundPanel"
        Spacing="10"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Margin="0,0,200,0"
        >
        <TextBlock>Background buttons</TextBlock>
        <Button
            Click="Button_Click"
            AccessKey="A"
            ProcessKeyboardAccelerators="Button_ProcessKeyboardAccelerators">Popup 1</Button>
        <Button
            Click="Button_Click">Popup 2</Button>
    </StackPanel>
    <Grid
        x:Name="PopupGrid"
        Background="#8000"
        TabFocusNavigation="Cycle"
        Visibility="Collapsed">
        <StackPanel
            Spacing="10"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Margin="200,0,0,0">
            <TextBlock>Popup buttons</TextBlock>
            <Button
                x:Name="InPopupButton1"
                Click="Button_Click">In popup 1</Button>
            <Button
                x:Name="InPopupButton2"
                Click="Button_Click">In popup 2</Button>
        </StackPanel>
    </Grid>
</Grid>

隐藏代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
    TogglePopup();
}

private void Button_ProcessKeyboardAccelerators(UIElement sender, ProcessKeyboardAcceleratorEventArgs args)
{
    if (args.Key == Windows.System.VirtualKey.A &&
        args.Modifiers == Windows.System.VirtualKeyModifiers.Control)
    {
        TogglePopup();
    }
}

private void TogglePopup()
{
    BackgroundContentControl.IsEnabled = !BackgroundContentControl.IsEnabled;
    if (PopupGrid.Visibility != Visibility.Visible)
    {
        PopupGrid.Visibility = Visibility.Visible;
        BackgroundPanel.IsHitTestVisible = false;
        InPopupButton1.Focus(FocusState.Programmatic);
    }
    else
    {
        PopupGrid.Visibility = Visibility.Collapsed;
        BackgroundPanel.IsHitTestVisible = true;
    }
}

现在,访问键、加速器或其他自定义输入逻辑(如果支持的话)会像屏幕阅读器支持一样难以大规模阻止。为此——你可能想做更多的事情。我能想到的选项很少......将背景内容包装在

ContentControl
中,您可以使用控制整个内容树的启用状态的
IsEnabled
属性禁用它。请参阅下面的示例。您还可以暂时从树中删除背景内容 (
RootGrid.Children.Remove()
) 并在完成后添加回来。如果您仍然想让背景在上下文中保持可见 - 您可以将其捕获为
RenderTargetBitmap
并仅在背景中的
Image
控件中显示位图。

<Grid>
    <ContentControl
        x:Name="BackgroundContentControl"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch"
        HorizontalContentAlignment="Stretch"
        VerticalContentAlignment="Stretch">
        <StackPanel
            x:Name="BackgroundPanel"
            Spacing="10"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Margin="0,0,200,0">
            <TextBlock>Background buttons</TextBlock>
            <Button
                Click="Button_Click"
                AccessKey="A"
                ProcessKeyboardAccelerators="Button_ProcessKeyboardAccelerators">Popup 1</Button>
            <Button
                Click="Button_Click">Popup 2</Button>
        </StackPanel>
    </ContentControl>
    <Grid
        x:Name="PopupGrid"
        Background="#8000"
        TabFocusNavigation="Cycle"
        Visibility="Collapsed">
        <StackPanel
            Spacing="10"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Margin="200,0,0,0">
            <TextBlock>Popup buttons</TextBlock>
            <Button
                x:Name="InPopupButton1"
                Click="Button_Click">In popup 1</Button>
            <Button
                x:Name="InPopupButton2"
                Click="Button_Click">In popup 2</Button>
        </StackPanel>
    </Grid>
</Grid>

0
投票

不幸的是,似乎没有人知道(除了斯卡昆先生,他给出了错误的答案,而且从未费心修改)。

因此,我的解决方案(最简单的)是隐藏有问题的元素 - 我找不到任何其他方法来“禁用”网格。

如果我想正确禁用它,我必须编写一个递归函数来查找网格子级中的所有 FrameworkElement 并设置 IsEnabled = false。

© www.soinside.com 2019 - 2024. All rights reserved.