2011-01-11 30 views
3

我正在使用WPF组合框,并且我注意到一个问题,即在源自身处于进程中时更新绑定源后,组合框未显示正确的绑定值从绑定更新。WPF组合框在更新绑定源后不显示正确的值

我已经把一个简单的例子来演示这一点。在这个例子中,我有一个包含4个项目(字符串“A”,“B”,“C”和“D”)的组合框。在组合框上的SelectedItem与数据上下文上的属性(称为ComboSelectedItem)之间存在双向绑定。

预期的功能是,如果用户从组合框中选择“A”,“B”或“C”,则datacontext中的逻辑将尝试将组合框上的选择重置为“D”。然而,相反,如果用户从组合框中选择“A”,则选择保持在“A”上。

这里是下面的示例代码:

MainWindow.xaml:

<Window x:Class="Testing.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 

    <Label Grid.Row="0" Grid.Column="0" Margin="10,10,10,10">Combobox test:</Label> 
    <ComboBox Grid.Row="0" Grid.Column="1" Margin="10,10,10,10" x:Name="comboBox" 
       ItemsSource="{Binding Path=ComboBoxItems}" Width="80" 
       SelectedItem="{Binding Path=ComboSelectedItem, Mode=TwoWay}"/> 

     </Grid> 
</Window> 

和代码隐藏它:

using System; 
using System.Windows; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Threading; 

namespace Testing 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private ObservableCollection<String> items; 
     public ObservableCollection<String> ComboBoxItems 
     { 
      get 
      { 
       if (items == null) 
       { 
        items = new ObservableCollection<string>(); 
        items.Add("A"); 
        items.Add("B"); 
        items.Add("C"); 
        items.Add("D"); 
       } 

       return items; 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private string comboSelectedItem; 
     public string ComboSelectedItem 
     { 
      get { return comboSelectedItem; } 
      set 
      { 
       comboSelectedItem = value; 

       if (PropertyChanged != null) 
        PropertyChanged(this, new PropertyChangedEventArgs("ComboSelectedItem")); 

       //if value != D, set to D 
       if (ComboSelectedItem != "D") 
       { 
        ComboSelectedItem = "D"; 
       } 
      } 
     } 
    } 
} 

我发现,如果我排队了ComboSelectedItem设置,以便它发生在UI线程,然后这将工作,例如

public string ComboSelectedItem 
    { 
     get { return comboSelectedItem; } 
     set 
     { 
      comboSelectedItem = value; 

      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("ComboSelectedItem")); 

      //if value != D, set to D 
      if (ComboSelectedItem != "D") 
      { 
       ThreadPool.QueueUserWorkItem(delegate(Object theElement) 
       { 
        UIElement elem = (UIElement)theElement; 
        elem.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() 
         { 
          ComboSelectedItem = "D"; 
         }); 
       }, comboBox); 
      } 
     } 
    } 

不过,我不能完全确定为什么这工作,反正我不希望要为我的应用程序的所有组合框可能发生这样的情况下做到这一点。

相反,Combobox或其他方法可以解决这个问题吗?谢谢。

回答

1

这将有助于

private string comboSelectedItem; 
    public string ComboSelectedItem 
    { 
     get { return comboSelectedItem; } 
     set 
     { 
      var origValue = "D"; 

      if (value == comboSelectedItem) 
       return; 

      comboSelectedItem = value; 
      //if value != D, set to D 
      if (ComboSelectedItem != "D") 
      { 
       // change the value back, but do so after the 
       // UI has finished it's current context operation. 
       Application.Current.Dispatcher.BeginInvoke(
         new Action(() => 
         { 
          comboSelectedItem = origValue; 
          if (PropertyChanged != null) 
           PropertyChanged(this, new PropertyChangedEventArgs("ComboSelectedItem")); 
         }), DispatcherPriority.ContextIdle, null); 
       // Exit early. 
       return; 
      } 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("ComboSelectedItem")); 

     } 
    } 

检查here更多

+0

谢谢六必居。我希望避免这样做,但这可能是目前唯一的解决方案。感谢您发布该链接 - 让我更好地了解它如何/为什么会起作用。 – Joe 2011-01-12 22:39:54