代码改变世界

【原】Bug of Silverlight ComboBox?

2009-03-29 14:57  拖鞋不脱  阅读(3259)  评论(4编辑  收藏  举报

没想到一个小小的ComboBox的选中问题搞得我连午饭都没吃上……

目前找到了几个解决方案,但还有不明之处。

界面:

<UserControl x:Class="SilverlightApplication2.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="Yellow" >
        <StackPanel Orientation="Horizontal" Height="300">
            <ComboBox Width="200" Height="30" x:Name="ComSelector" ></ComboBox>
            <Button Width="50" Height="50" Click="Button_Click"></Button>
        </StackPanel>
    </Grid>
</UserControl>

很简单,一个ComboBox,一个Button而已。

后台:

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
        Init(0);
    }

    private void Init(int x)
    {
        //清空ComSelector的Items
        ComSelector.Items.Clear();
        //添加10个Item
        for (int i = 0; i < 10; i++)
        {
            ComboBoxItem item = new ComboBoxItem()
            {
                Content = i,
                //若i==x,则Item为选中状态
                IsSelected = (i==x)
            };
            ComSelector.Items.Add(item);
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Random rand = new Random(DateTime.Now.Millisecond);
        Init(rand.Next(0,10));
    }
}

也很简单,想要实现的逻辑是:每次点击Button,为Comobox重新添加10个Item,然后设置某个item的选中状态为true。

现在的情况是:

在不打开ComboBox的情况下,点击按钮,工作正常;但只要点开ComboBox,无论是否选中某一项,再点击Button,就会出异常(“值不在预期的范围内”)

目前已经确定的是:

  • 如果注释掉“ComSelector.Items.Clear(); ”运行不会有问题,但不符合功能要求,因为相当于每次点击按钮都额外添加了10个Item;
  • 同样,注释掉“IsSelected = (i==x) ”运行也不会有问题,同样不符合功能要求……

当前的两个解决方案:

1、由同事提供:

Init(int x)变为:

private void Init(int x)
{
    //清空ComSelector的Items
    ComSelector.Items.Clear();
    ComboBoxItem seletedItem = null;
    //添加10个Item
    for (int i = 0; i < 10; i++)
    {
        ComboBoxItem item = new ComboBoxItem()
        {
            Content = i,
            //若i==x,则Item为选中状态
            //IsSelected = (i==x)
        };
        if (i == x)
        {
            seletedItem = item;
        }
        ComSelector.Items.Add(item);
    }
    if (seletedItem != null)
    {
        ComSelector.Items.Dispatcher.BeginInvoke(() => { ComSelector.SelectedItem = seletedItem; });
    }
}

是,看起来比较诡异,不过能Work。

2.由http://silverlight.net/forums/t/62777.aspx提供:

private void Init(int x)
{
    //清空ComSelector的Items
    ComSelector.Items.Clear();
    ComboBoxItem seletedItem = null;
    //添加10个Item
    for (int i = 0; i < 10; i++)
    {
        ComboBoxItem item = new ComboBoxItem()
        {
            Content = i,
            //若i==x,则Item为选中状态
            //IsSelected = (i==x)
        };
        if (i == x)
        {
            seletedItem = item;
        }
        ComSelector.Items.Add(item);
    }
    ComSelector.UpdateLayout();
    if (seletedItem != null)
    {
        ComSelector.SelectedItem = seletedItem;
    }
}

先UpdateLayout(),再设SelectedItem,同样工作正常。

简化版:

private void Init(int x)
{
    //清空ComSelector的Items
    ComSelector.Items.Clear();
    ComSelector.UpdateLayout();
    //添加10个Item
    for (int i = 0; i < 10; i++)
    {
        ComboBoxItem item = new ComboBoxItem()
        {
            Content = i,
            //若i==x,则Item为选中状态
            IsSelected = (i==x)
        };
        ComSelector.Items.Add(item);
    }
}

那么现在的问题是,在点开、收起ComboBox的PopUp之后,它到底干了些什么?之后的Items.Clear又触犯了哪位的领地,ComboBoxItem的IsSelected属性的设置到底影响了谁……