WPF - Невозможно удалить элементы из элемента управления с привязкой к базе данных - PullRequest
1 голос
/ 14 июля 2009

Я создал комбинированный список и привязал его к коллекции observableCollection.

Что-то вроде myCmbBox.ItemsSource = myObsCollObj

Мой сценарий - onLoad приложения. Я заполню свою коллекцию observableCollection некоторыми значениями. Теперь мой пользовательский интерфейс также обновляется с этими значениями автоматически. Если пользователь выбирает другое значение из другого комбинированного списка (скажем, combobox2), мне нужно очистить все существующие элементы из myCmbBox. Я попытался сделать это, используя следующие параметры

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

   myCmbBox = null;
   myCmbBox.Items.Clear()

Ни один из вышеперечисленных параметров не работает, и я получил исключение, говорящее "Значение не может быть нулевым".

Теперь у меня вопрос, как мне очистить мою коллекцию и добавить новые значения (которые также должны обновить мой интерфейс)

Спасибо, Ranjith

Обновление с кодом

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 ]

2 голосов
/ 27 августа 2009

Некоторые люди используют манекен «выйти из машины» и снова войти в машину:

myCmbBox.ItemsSource = null;
myCmbBox.ItemsSource = yourLoadMethod();
2 голосов
/ 14 июля 2009

Похоже, что ваш ComboBox имеет свойство SelectedItem или SelectedValue, привязанное к чему-то, что не может быть нулевым. Поэтому, когда вы пытаетесь очистить коллекцию, с которой связано свойство Items ComboBox, она пытается присвоить этому свойству значение «null», и возникает исключение.

Вероятно, есть действительно хороший WPF-й способ обойти это. Вероятно, я бы начал с попытки временно приостановить привязку, установив режим обновления на Явное, а затем очистив коллекцию:

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

Это всего лишь предложение. Возможно, я лаю не на том дереве, но это может подсказать вам, почему вы получаете ошибку.

Обновление

Ух ты - это много кода. Жаль, что вы не смогли уменьшить его до минимума, необходимого для воспроизведения проблемы.

Я предполагаю, что ваше исключение выдается из обработчика события cmbRecipeType_SelectionChanged. Если это так, у вас есть два варианта:

  1. Поместите точку останова внутри этого метода и выясните, что вызывает исключение. Вероятно, это что-то простое, например, в первой строке с нулевым значением:

    строка selectedRecipeType = cmbRecipeType.SelectedItem как строка;

Если это правда, вы, вероятно, могли бы сразу же это исправить:

if (selectedRecipeType == null) return;

Что предотвратит доступ любого последующего кода к selectedRecipeType, как если бы он не был нулевым.

  1. Сделайте что-то похожее на то, что я изначально предлагал, и временно отсоедините этот обработчик событий от вашего ComboBox, прежде чем очистить элементы. Затем сразу же подключите его.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...