我创建了一个组合框并将其绑定到一个observableCollection。
像myCmbBox.ItemsSource = myObsCollObj
之类的东西我的场景是onLoad应用程序我将使用一些值填充我的observableCollection。现在,我的UI也会自动刷新这些值。如果用户从另一个组合框中选择一个不同的值(比如说combobox2),我现在需要清除myCmbBox中的所有现有项目。我尝试使用以下选项
myObsCollObj.Remove()
myObsCollObj.RemoveAt()
myObsCollObj.Clear()
(myCmbBox.ItemsSource as ObservableCollection<string>).Remove()
myCmbBox = null;
myCmbBox.Items.Clear()
上述选项均无效,我得到一个例外,说“价值不能为空”。
现在我的问题是,如何清除我的收藏并添加新值(这也应该刷新我的用户界面)
谢谢, 兰芝斯
使用代码更新
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");
}
}
}
答案 0 :(得分:2)
听起来您的ComboBox将其SelectedItem或SelectedValue属性绑定到不允许为null的内容。因此,当您尝试清除ComboBox的Items属性所绑定的集合时,它会尝试为该属性分配“null”并引发异常。
可能有一种非常好的WPF-y方式来解决它。我可能首先尝试通过将其更新模式设置为Explicit来暂时挂起绑定,然后清除集合:
var binding = BindingOperations.GetBinding(myCmdBox, ComboBox.SelectedItemProperty);
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
myObservableCollection.Clear();
// repopulate the collection here
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
这只是一个建议。我可能正在咆哮错误的树,但它可能会给你一些线索,说明你为什么会收到错误。
<强>更新强>
哇 - 这是很多代码。遗憾的是你无法将其降低到重现问题所需的最低限度。我假设您的异常是从cmbRecipeType_SelectionChanged
事件处理程序中抛出的。如果是这种情况,您有两种选择:
在该方法中放置一个断点,找出抛出异常的内容。它可能很简单,就像第一行产生一个空值:
string selectedRecipeType = cmbRecipeType.SelectedItem as string;
如果这是真的,你可能会在此之后直接打击它:
if (selectedRecipeType == null) return;
这将阻止任何后续代码访问selectedRecipeType,就像它是非空的一样。
答案 1 :(得分:2)
有些人使用假人的方法“下车”并再次进入车内:
myCmbBox.ItemsSource = null;
myCmbBox.ItemsSource = yourLoadMethod();