【问题标题】:Silverlight ComboBox force reselect SelectedItemSilverlight ComboBox 强制重新选择 SelectedItem
【发布时间】:2011-08-17 06:32:50
【问题描述】:

我有一个绑定到 ComboBox 的项目列表。当用户选择一个项目时,我想取消选择并选择一个不同的项目。这必须在 SelectedItem 绑定到的属性的设置器中发生。我正在使用 Silverlight 3。

ComboBox 中每个项目的数据模型:

public class DataItem
{
    public int Id { get; set; }
    public string Name { get; set; }
}

设置为 DataContext 的对象:

public class DataContainer : INotifyPropertyChanged
{

    public DataContainer()
    {
        itemList = new List<DataItem>();
        itemList.Add(new DataItem() { Id = 1, Name = "First" });
        itemList.Add(new DataItem() { Id = 2, Name = "Second" });
        itemList.Add(new DataItem() { Id = 3, Name = "Third" });
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private DataItem selectedItem;
    public DataItem SelectedItem
    {
        get { return selectedItem; }
        set
        {
            if (value != null && value.Id == 2)
                value = itemList[0];
            selectedItem = value;
            NotifyPropertyChanged("SelectedItem");
        }
    }

    private List<DataItem> itemList;
    public List<DataItem> ItemList
    {
        get { return itemList; }
        set { itemList = value; NotifyPropertyChanged("DataList"); }
    }

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

xaml 的相关位:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <ComboBox x:Name="comboBox" DisplayMemberPath="Name" Width="100" ItemsSource="{Binding ItemList}" SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"/>
        <Button Content="Set to First" Width="100" Click="Button_Click"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Selected item: "/>
        <TextBlock Text="{Binding SelectedItem.Id}"/>
        <TextBlock Text=" - "/>
        <TextBlock Text="{Binding SelectedItem.Name}"/>
    </StackPanel>
</StackPanel>

看起来我的代码在用户选择第二个项目时选择第一个项目正在工作。所选项目实际上设置为“第一个”,而 ComboBox 仍显示“第二个”,就好像它被选中一样。

有没有办法强制 ComboBox 重绘或重新考虑它应该在视觉上标记为选中的内容?

我通过上面提到的 Button_Click 方法执行此操作,并且它有效:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var c = DataContext as DataContainer;
        if (c != null)
        {
            c.SelectedItem = null;
            c.SelectedItem = c.ItemList[0];
        }
    }

但是如果我像我需要的那样从设置器中进行设置,那么设置为 null 然后我想要的值不起作用。

【问题讨论】:

    标签: silverlight binding combobox selection


    【解决方案1】:

    我可能已经为您找到了解决方案。通过执行以下操作,我能够得到我认为您要求的工作:

    public DataItem SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (value != null && value.Id == 2)
            {
                value = itemList[0];
                UpdateUI();  // Call this to force the UI to update.
            }
            _selectedItem = value;
            NotifyPropertyChanged("SelectedItem");
    
        }
    }
    
    private void UpdateUI()
    {
        ThreadPool.QueueUserWorkItem(
            o =>
            {
                Thread.Sleep(1);
    
                Deployment.Current.Dispatcher.BeginInvoke(()=>
                {
                    _selectedItem = null;
                    NotifyPropertyChanged("SelectedItem");
                    _selectedItem = itemList[0];
                    NotifyPropertyChanged("SelectedItem");
                });
            });
    }
    

    我希望我能向你解释为什么这是有效的,但我只能猜测。基本上,它退出 UI 线程,然后稍后通过 Dispatcher.BeginInvoke() 调用重新进入。这似乎使 ComboBox 控件有时间从用户交互中更新自身,然后响应 Dispatcher 执行。

    我发现的一个问题是,在多次执行线程代码后,Silverlight 似乎有点不稳定。增加 Thread.Sleep 时间似乎有帮助。我认为这个解决方案适用于大多数情况,不会成为问题。

    【讨论】:

    • 我真的希望避免这种方法。如果我无法弄清楚如何让 ComboBox 自行修复,那么我想我必须这样做。
    【解决方案2】:

    您不必像 grimus 建议的那样将线程排队等待 1 秒。这也应该适合你:

    public DataItem SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            NotifyPropertyChanged("SelectedItem");
    
            if (value != null && value.Id == 2)
            {
                Diployment.Current.Dispatcher.BeginInvoke(() => { 
                              _selectedItem = itemList[0];               
                              NotifyPropertyChanged("SelectedItem"); });
            }
    
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      相关资源
      最近更新 更多