Win8 ComboBox IsDropDownOpen +可视性导致界面故障

本文关键字:界面 故障 可视性 ComboBox IsDropDownOpen Win8 | 更新日期: 2023-09-27 18:01:24

我正在使用XAML和c#开发Windows 8应用程序。我的ComboBox有一个问题,我有一个简单的例子来演示它。

  1. 将以下内容添加到布局感知页面(New BasicPage)

    <ComboBox x:Name="comboBox1" DropDownClosed="comboBox1_DropDownClosed" Visibility="Collapsed" HorizontalAlignment="Left" Margin="179,217,0,0" Grid.Row="1" VerticalAlignment="Top" Width="998" Height="51">
        <x:String>Option 1</x:String>
        <x:String>Option 2</x:String>
        <x:String>Option 3</x:String>
    </ComboBox>
    <Button Click="Button_Click" Margin="585,130,0,416" Grid.Row="1" Height="82" Width="154">
        <Viewbox>
            <TextBlock Text="Press Me" />
        </Viewbox>
    </Button>
    
  2. 将此添加到页面的CodeBehind

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
        comboBox1.IsDropDownOpen = true;
    }
    private void comboBox1_DropDownClosed(object sender, object e)
    {
        comboBox1.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    }
    

: 当按下按钮时,应该出现ComboBox,并且应该展开选项,允许用户选择一个。一旦用户选择了一个选项,组合框就会消失。

实际结果:

按下按钮后,什么也没发生。如果再次按下该按钮,则组合框将出现故障状态,并且应用程序基本上没有响应。(所有的输入都指向组合框,它永远不会关闭。

注意:DropDownClosed事件在Button_Click事件之后立即触发。删除事件处理程序不会改变任何东西,但有趣的是,DropDownClosed事件正在触发。

拒绝解决方案:建议我在Visibility修改生效后,用Dispatcher.RunAsync设置IsDropDownOpen。这似乎是一个竞争条件,因为它只在某些时间内起作用。如果有一种方法可以确认ComboBox已经呈现可见,将此检查添加到RunAsync方法中可以解决这个问题。

作为一种变通方法,我目前正在延迟Dispatcher。运行异步为200毫秒,这是一个恼人的解决方案。还有其他想法吗?

Win8 ComboBox IsDropDownOpen +可视性导致界面故障

你是对的,你需要确保comboBox1实际上呈现可见,之前试图设置IsDropDownOpen。方法是通过Dispatcher:

进行第二次调用。
private void Button_Click(object sender, RoutedEventArgs e)
{
    comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
    Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => comboBox1.IsDropDownOpen = true);
}

多么讨厌的虫子啊?

一个简单的解决方法是使用不透明度而不是可见度属性。按预期运行:

   <ComboBox x:Name="comboBox1" DropDownClosed="comboBox1_DropDownClosed" Opacity="0" HorizontalAlignment="Left" Margin="179,217,0,0" Grid.Row="1" VerticalAlignment="Top" Width="998" Height="51">
        <x:String>Option 1</x:String>
        <x:String>Option 2</x:String>
        <x:String>Option 3</x:String>
    </ComboBox>

    private void Button_Click(object sender, RoutedEventArgs e) {
        comboBox1.Opacity = 1;
        comboBox1.IsDropDownOpen = true;
    }
    private void comboBox1_DropDownClosed(object sender, object e) {
        comboBox1.Opacity = 0;
    }

干杯!

我在我的台式机和Surface设备上测试了以下功能,似乎一直都能正常工作。这是延迟设置IsDropDownOpen的变体。我知道你可能已经尝试了一些产生竞争条件的变体。我没有看到一个比赛条件,所以希望它也适用于你。

// need this for Task
using System.Threading.Tasks;
...
// note async keyword added to function signature
async private void Button_Click(object sender, RoutedEventArgs e)
{
    comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
    // add small delay before opening dropdown
    await Task.Delay(1);
    comboBox1.IsDropDownOpen = true;
}