2009-07-14 91 views
1

我创建了一个组合框,并将其绑定到一个observableCollection。WPF - 无法清除数据绑定项目itemscontrol

喜欢的东西myCmbBox.ItemsSource = myObsCollObj

我的情况是,我将用一些值填充我的ObservableCollection应用的onLoad。现在,我的UI也会自动刷新这些值。如果用户从另一个组合框(例如combobox2)中选择了一个不同的值,我现在需要清除myCmbBox中的所有现有项目。我试图这样做使用下列选项

myObsCollObj.Remove() 
    myObsCollObj.RemoveAt() 
    myObsCollObj.Clear() 
    (myCmbBox.ItemsSource as ObservableCollection<string>).Remove() 

    myCmbBox = null; 
    myCmbBox.Items.Clear() 

无上述选项的工作,我得到了一个异常说:“值不能为空”。

我的问题是现在,我该如何清除我的采集和添加新值(这应该更新我的UI以及)

感谢, 兰芝斯

更新与代码

XAML

<Page x:Class="ThrowAwayProto.Page1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Page1"> 
    <StackPanel> 
     <Label HorizontalAlignment="Center">Environment Modules</Label> 
     <ComboBox Name="lstEnv" SelectionChanged="lstEnv_SelectionChanged"></ComboBox> 

     <Label HorizontalAlignment="Center">Module Ids</Label> 
     <ComboBox Name="cmbModId" SelectionChanged="cmbModId_SelectionChanged"></ComboBox> 

     <Label HorizontalAlignment="Center">Environment Modules</Label> 
     <ListBox Name="lstSites"></ListBox> 

     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="600"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 
      <Grid Grid.Column="0"> 
       <Grid.RowDefinitions> 
        <!-- Recipe Type --> 
        <RowDefinition Height="30"/> 
        <!-- Recipe Mode --> 
        <RowDefinition Height="30"/> 
        <!-- Include expired recipe --> 
        <RowDefinition Height="30"/> 
        <!-- Search for promoted recipe --> 
        <RowDefinition Height="30"/> 
        <!-- Site --> 
        <!--<RowDefinition Height="30"/>--> 
        <!-- Activity --> 
        <!--<RowDefinition Height="30"/>--> 
       </Grid.RowDefinitions> 

       <StackPanel Orientation="Horizontal" Grid.Row="0" Width="100"> 
        <Label>Recipe Type</Label> 
        <ComboBox Name="cmbRecipeType" SelectionChanged="cmbRecipeType_SelectionChanged"/> 
       </StackPanel> 

       <StackPanel Orientation="Horizontal" Grid.Row="1"> 
        <Label>Recipe Mode</Label> 
        <ComboBox Name="cmbRecipeMode"> 
         <ComboBoxItem>PRODUCTION</ComboBoxItem> 
         <ComboBoxItem>ENGINEERING</ComboBoxItem> 
        </ComboBox> 
       </StackPanel> 

       <StackPanel Orientation="Horizontal" Grid.Row="2"> 
        <Label>Include Expired Recipe?</Label> 
        <RadioButton>Yes</RadioButton> 
        <RadioButton>No</RadioButton> 
       </StackPanel> 

       <StackPanel Orientation="Horizontal" Grid.Row="3"> 
        <Label>Search for promoted Recipe?</Label> 
        <CheckBox Name="chkPromRecipe"/> 
       </StackPanel> 

       <!--<StackPanel Orientation="Horizontal" Grid.Row="4"> 
        <Label>Site</Label> 
        <ComboBox Name="cmbSite"/> 
       </StackPanel> 

       <StackPanel Orientation="Horizontal" Grid.Row="5"> 
        <Label>Activity</Label> 
        <ComboBox Name="cmbActivity"/> 
       </StackPanel>-->     

      </Grid> 

      <Grid Name="grdCol2" Grid.Column="1"> 

      </Grid> 
     </Grid> 

     <Button Name="btnSearch" Click="btnSearch_Click">Search</Button> 

    </StackPanel> 
</Page> 

背后的代码

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Xml.Linq; 
using Intel.ATTD.Data; 
using Intel.Auto.MW.Frameworks; 
using System.Collections.ObjectModel; 

namespace ThrowAwayProto 
{ 
    /// <summary> 
    /// Interaction logic for Page1.xaml 
    /// </summary> 
    public partial class Page1 : Page 
    { 
     private string _types; 

     private Dictionary<string,string> _envList; 
     private Dictionary<string, string> _modNameToId; 
     private Dictionary<string, string> _selCritNameToId; 
     private List<string> _selCritNames; 
     private Dictionary<string, ObservableCollection<string>> _selCritNameToList; 

     public ObservableCollection<string> _modIdList { get; set; } 
     public ObservableCollection<string> _siteList { get; set; } 
     public ObservableCollection<string> _recipeTypes { get; set; } 

     public Page1() 
     { 
      InitializeComponent(); 
      _envList = new Dictionary<string, string>(); 
      _modIdList = new ObservableCollection<string>(); 
      _siteList = new ObservableCollection<string>(); 
      _modNameToId = new Dictionary<string, string>(); 
      _recipeTypes = new ObservableCollection<string>(); 
      _selCritNames = new List<string>(); 
      _selCritNameToId = new Dictionary<string, string>(); 
      _selCritNameToList = new Dictionary<string, ObservableCollection<string>>(); 

      cmbModId.ItemsSource = _modIdList; 
      lstSites.ItemsSource = _siteList; 

      LoadEnvModule(); 
      GetSites(); 
     } 

     /// <summary> 
     /// First step in ASNC 
     /// </summary> 
     private void LoadEnvModule() 
     { 

      string environments = ConsoleApplication1.Program.CallEnvironMentModuleMgntService_GetAllEnvironments(); 

      // Load Xml 
      XElement document = XElement.Parse(environments); 

      IEnumerable<XElement> childElements = 
       from envModule in document.Elements("Environment") 
       select envModule; 

      foreach (XElement el in childElements) 
       _envList.Add(el.Element("Name").Value, el.Element("Id").Value); 

      List<string> envNames = new List<string>(); 
      foreach (string names in _envList.Keys) 
       envNames.Add(names); 

      // Set the ListBox value 
      lstEnv.ItemsSource = envNames; 
     } 

     /// <summary> 
     /// Step 2 
     /// </summary> 
     private void GetModuleByEnvId() 
     { 
      string selectedEnvId = lstEnv.SelectedItem as string; 
      selectedEnvId = _envList[selectedEnvId]; 

      DataCollection reqDC = new DataCollection("GetModuleByEnvID"); 
      reqDC.add(new Parameter("Idsid", "rchevan"));    
      reqDC.add(new Parameter("Id", selectedEnvId)); 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "EnvModuleMgntService", "GetModuleByEnvID"); 

      string modules = reply[0].toXML(); 
      // Extract required info 
      // Load Xml 
      XElement document = XElement.Parse(modules); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("Module") 
       select mod; 

      if (_modIdList.Count > 0) 
      { 
       _modNameToId.Clear(); 
       _modIdList.Clear(); 
      } 

      foreach (XElement el in childElements) 
      {     
       _modNameToId.Add(el.Element("Name").Value, el.Element("Env_Mod_Id").Value); 
       _modIdList.Add(el.Element("Name").Value); 
      } 

      // Rebind when a new environment is selected 

     } 

     private static DataCollection[] InvokeATMIA(Request[] requests, string serName, string opName) 
     { 
      DataCollection[] reply = null; 
      ATMIAProxy proxy = new ATMIAProxy(); 

      ATMIAMessage input = new ATMIAMessage(); 
      input.AddParameter("ServiceName", serName); 
      input.AddParameter("OperationName", opName); 
      input.AddObject(requests); 

      ATMIAMessage output = proxy.InvokeMethod(input); 

      if (output.GetTxnSuccess()) 
      { 
       return output.GetBody<DataCollection[]>(); 
      } 

      return null; 
     } 

     private void lstEnv_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     {    
      GetModuleByEnvId(); 
     } 

     /// <summary> 
     /// Call GetModuleAliasData 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 
     private void cmbModId_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      // Get Module Alias data 
      // This is the actual search recipe 
      string selectedModId = cmbModId.SelectedItem as string; 

      //string selectedModId = "DEFLUX"; 
      selectedModId = _modNameToId[selectedModId]; 

      DataCollection reqDC = new DataCollection("GetModuleAliasData"); 
      reqDC.add(new Parameter("Env_Mod_Id", selectedModId)); 
      reqDC.add(new Parameter("Idsid", "rchevan")); 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "EnvModuleMgntService", "GetModuleAliasData"); 

      // Load the Recipe Types and SelCritNames here 
      _types = reply[0].toXML(); 
      // Extract required info 
      // Load Xml 
      XElement document = XElement.Parse(_types); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("RecipeType") 
       select mod; 

      foreach (XElement el in childElements) 
       _recipeTypes.Add(el.Element("RecipeTypeName").Value); 

      cmbRecipeType.ItemsSource = _recipeTypes; 


     } 

     private void GetSites() 
     { 
      DataCollection reqDC = new DataCollection("GetEnvToSite"); 
      reqDC.add(new Parameter("Idsid", "rchevan")); 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "EnvModuleMgntService", "GetEnvToSite"); 

      string sites = reply[0].toXML(); 
      // Extract required info 
      // Load Xml 
      XElement document = XElement.Parse(sites); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("Environment").Elements("Site") 
       select mod; 

      foreach (XElement el in childElements) 
       _siteList.Add(el.Element("SiteName").Value); 

     } 

     private void GetSearchAttributes() 
     { 
      string selectedModId = cmbModId.SelectedItem as string; 
      //string selectedModId = "DEFLUX"; 
      selectedModId = _modNameToId[selectedModId]; 

      DataCollection reqDC = new DataCollection("GetSearchAttributes"); 
      reqDC.add(new Parameter("Env_Mod_Id", selectedModId)); 
      reqDC.add(new Parameter("EntityRequired", "N")); 
      reqDC.add(new Parameter("Idsid", "rchevan")); 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "RecipeSearchService", "GetSearchAttributes"); 

      string selCrits = reply[0].toXML(); 
      // Extract required info 
      // Load Xml 
      XElement document = XElement.Parse(selCrits); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("Sel_Crit_Ids") 
       select mod; 

      if (_selCritNameToId.Count > 0) 
       _selCritNameToId.Clear(); 

      foreach (XElement el in childElements) 
       _selCritNameToId.Add(el.Element("Sel_Crit_Name").Value, el.Element("Sel_Crit_Id").Value); 

      GetOptSearchAttributes(); 

     } 

     private void GetOptSearchAttributes() 
     { 
      DataCollection reqDC = new DataCollection("GetSearchAttributes"); 
      reqDC.add(new Parameter("Idsid", "rchevan")); 

      DataCollection selCritDC = new DataCollection("Sel_Crit_Ids"); 
      foreach (string selCritName in _selCritNames) 
      { 
       string selCritId = _selCritNameToId[selCritName]; 

       selCritDC.add(new Parameter("Sel_Crit_Id", selCritId)); 
       reqDC.add(selCritDC); 
      } 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "RecipeSearchService", "GetOptSearchAttributeValues"); 

      string instSelCrits = reply[0].toXML(); 
      // Extract required info 
      // Load Xml 
      XElement document = XElement.Parse(instSelCrits); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("InstanceForSelCrit") 
       select mod; 

      //if (_selCritNameToId.Count > 0) 
      // _selCritNameToId.Clear(); 

      foreach (string selCrit in _selCritNames) 
      { 
       string selCritId = _selCritNameToId[selCrit]; 

       ObservableCollection<string> selCritNameList = new ObservableCollection<string>(); 
       _selCritNameToList.Add(selCrit, selCritNameList); 

       foreach (XElement el in childElements) 
       { 
        string selCritRecv = el.Element("Sel_Crit_Id").Value; 

        if (string.Equals(selCritId, selCritRecv)) 
        { 
         string selCritName = el.Element("Sel_Crit_Inst_Name").Value; 
         selCritNameList.Add(selCritName); 
        } 
       } 
      } 

      GridLengthConverter myGridLengthConverter = new GridLengthConverter(); 
      GridLength gl1 = (GridLength)myGridLengthConverter.ConvertFromString("50"); 

      // Populate values to the right hand side of the 
      // search screen 
      int counter = 0; 
      foreach (string selCrit in _selCritNames) 
      { 
       ComboBox cmbBox = new ComboBox(); 
       cmbBox.ItemsSource = _selCritNameToList[selCrit]; 
       Grid.SetRow(cmbBox, counter); 
       Grid.SetColumn(cmbBox, 1); 

       grdCol2.Children.Add(cmbBox); 

       ++counter; 
      } 

     } 

     /// <summary> 
     /// Based on the Recipe Type selected load other information 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 
     private void cmbRecipeType_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      string selectedRecipeType = cmbRecipeType.SelectedItem as string; 

      // Retrieve all Sel_Crit_Names to display 
      XElement document = XElement.Parse(_types); 

      IEnumerable<XElement> childElements = 
       from mod in document.Elements("RecipeType") 
       select mod; 

      GridLengthConverter myGridLengthConverter = new GridLengthConverter(); 
      GridLength gl1 = (GridLength)myGridLengthConverter.ConvertFromString("50"); 

      // Clear before adding new columns 
      grdCol2.ColumnDefinitions.Clear(); 
      grdCol2.RowDefinitions.Clear(); 

      ColumnDefinition colDef1 = new ColumnDefinition(); 
      ColumnDefinition colDef2 = new ColumnDefinition(); 
      grdCol2.ColumnDefinitions.Add(colDef1); 
      grdCol2.ColumnDefinitions.Add(colDef2); 

      int counter = 0; 

      if (_selCritNames.Count > 0) 
       _selCritNames.Clear(); 

      foreach (XElement el in childElements) 
      { 
       string recipeType = el.Element("RecipeTypeName").Value; 

       if (string.Equals(selectedRecipeType, recipeType)) 
       { 
        IEnumerable<XElement> aliases = 
        from mod in el.Elements("Aliases") 
        select mod; 

        foreach (XElement al in aliases) 
        { 
         string element = al.Element("Sel_Crit_Name").Value; 

         _selCritNames.Add(element); 

         Label label = new Label(); 
         label.Content = element; 

         RowDefinition row = new RowDefinition(); 
         grdCol2.RowDefinitions.Add(row); 
         grdCol2.RowDefinitions[counter].Height = gl1; 
         Grid.SetRow(label, counter); 
         Grid.SetColumn(label, 0); 

         grdCol2.Children.Add(label); 

         ++counter; 
        } 
        break; 
       } 

      } 



      // Now fill the values for the fields retrieved above 
      // in the loop 
      GetSearchAttributes(); 
     } 

     private void btnSearch_Click(object sender, RoutedEventArgs e) 
     { 
      DataCollection reqDC = new DataCollection("SearchLinkRecipe"); 
      reqDC.add(new Parameter("Env_Mod_Id", cmbModId.SelectedItem as string)); 
      reqDC.add(new Parameter("RecipeType", cmbRecipeType.SelectedItem as string)); 
      reqDC.add(new Parameter("RecipeMode", "PRODUCTION")); 
      reqDC.add(new Parameter("ExpiredRecipe", "N")); 
      reqDC.add(new Parameter("Site", "CHANDLER, ARIZONA")); 
      reqDC.add(new Parameter("PromotedStatus", "N")); 
      reqDC.add(new Parameter("SearchType", "Dummy")); 
      reqDC.add(new Parameter("LastUpdatedBy", "rchevan")); 

      DataCollection keyDC1 = new DataCollection("Key"); 
      keyDC1.add(new Parameter("KeyCriteria", _selCritNames[0])); 
      keyDC1.add(new Parameter("KeyValue", "*")); 
      reqDC.add(keyDC1); 

      DataCollection keyDC2 = new DataCollection("Key"); 
      keyDC2.add(new Parameter("KeyCriteria", _selCritNames[1])); 
      keyDC2.add(new Parameter("KeyValue", "*")); 
      reqDC.add(keyDC2); 

      //DataCollection keyDC3 = new DataCollection("Key"); 
      //keyDC3.add(new Parameter("KeyCriteria", "OPERATIONGROUP")); 
      //keyDC3.add(new Parameter("KeyValue", "*")); 
      //reqDC.add(keyDC3); 

      Request reqObj = new Request("Dummy", "Dummy"); 
      reqObj.add(reqDC); 

      Request[] requests = new Request[1]; 
      requests[0] = reqObj; 

      DataCollection[] reply = InvokeATMIA(requests, "RecipeSearchService", "SearchLinkRecipe"); 
     } 

    } 
} 

回答

2

听起来好像你的ComboBox的SelectedItem或SelectedValue属性绑定了某些不允许为null的东西。因此,当您尝试清除ComboBox的Items属性绑定的集合时,它试图为该属性分配“null”,并引发异常。

有可能是一个非常好的WPF-y方式来解决它。我可能会试图通过暂停通过设置它的更新模式,以明确的结合开始,然后清除集合:

var binding = BindingOperations.GetBinding(myCmdBox, ComboBox.SelectedItemProperty); 
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit; 
myObservableCollection.Clear(); 
// repopulate the collection here 
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; 

这只是一个建议。我可能会咆哮错误的树,但它可能会给你一些线索,为什么你会得到这个错误。

更新

哇 - 这是一个很大的代码。耻辱你无法将其降低到再现问题所需的最低限度。

我假设你的异常是从cmbRecipeType_SelectionChanged事件处理程序中抛出的。如果是这种情况,您有两种选择:

  1. 在该方法内部放置一个断点并找出抛出异常的内容。这可能很简单,就像第一行产生空值:

    string selectedRecipeType = cmbRecipeType。SelectedItem作为字符串;

如果这是真的,你很可能直后捶这:

if (selectedRecipeType == null) return; 

这将阻止任何后续的代码访问selectedRecipeType,仿佛这是不为空。

  1. 做一些类似于我最初的建议,并在清除项目之前暂时从ComboBox中取消绑定该事件处理程序。然后直接将它连接起来。
+0

嗨, 我不绑定将selectedItem或SelectedValue属性的任何地方。我做了类似 myCmbBox.ItemsSource = myObsCollObj; 只在应用程序启动过程中一次。然后,我所做的就是填充我的可观察集合,并自动刷新我的视图。现在,当我想清除可观察集合中的所有现有值时,我会得到一个异常。 – Jithu 2009-07-14 15:54:41

2

有些人用假人办法“从车里出来的”,并再次进入车内:

myCmbBox.ItemsSource = null; 
myCmbBox.ItemsSource = yourLoadMethod();