2011-05-02 47 views
4

我有一個綁定到組合框的項目列表。當用戶選擇一個項目時,我想取消選擇並選擇其他項目。這必須發生在SelectedItem綁定的屬性的setter中。我使用Silverlight 3Silverlight組合框強制重新選擇SelectedItem

在組合框的每個項目我的數據模型:

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

對象,它是設置到DataContext:XAML的

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)); 
    } 

} 

相關位:

<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重繪或重新考慮它應該在視覺上標記爲選中的內容嗎?

我做到這一點從上述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,然後,如果我從模子中不喜歡它,我需要我想要的值不工作。

回答

0

我可能爲您找到了解決方案。我能得到你問我想什麼做以下工作:

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控制時間從用戶交互中自行更新,然後響應分派器執行。

我發現的一個問題是,在多次執行線程代碼之後,Silverlight似乎變得有些笨拙。增加Thread.Sleep時間似乎有所幫助。我認爲這個解決方案適用於大多數情況,並不會成爲問題。

+0

我真的希望避免這種做法。如果我無法弄清楚如何使ComboBox自行修復,那麼我想我必須這樣做。 – 2011-05-04 16:20:14

0

你不必排隊一個線程,等待1秒鐘等待grimus建議。這應該也適用於你:

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"); }); 
     } 


    } 
}