2015-05-08 7 views
8

Ho un'applicazione WPF con un numero di caselle combinate che si collegano tra loro. Quando passo comboboxx # 1, # 2 combobox interruttori, eccSvuotamento e ricarica di una casella combinata combinata

Ecco il codice XAML per i 2 caselle combinate:

<ComboBox Grid.Row="1" Height="23" HorizontalAlignment="Right" Margin="0,12,286,0" ItemsSource="{Binding}" Name="CboDivision" VerticalAlignment="Top" Width="120" SelectionChanged="CboDivision_SelectionChanged" /> 
<ComboBox Height="23" HorizontalAlignment="Right" Margin="0,9,32,0" Name="CboCustomerList" ItemsSource="{Binding}" VerticalAlignment="Top" Width="120" SelectionChanged="CboCustomerList_SelectionChanged" Grid.Row="1" /> 

CboDivision viene popolata all'inizio e non ha bisogno di un reset. Ecco il codice che chiama il cambiamento di divisione, che dovrebbe innescare un cambiamento di cliente:

private void CboDivision_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    division = CboDivision.SelectedValue.ToString(); 
    CboCustomerList.ItemsSource = null; 

    BackgroundWorker customerWorker = new BackgroundWorker(); 
    customerWorker.DoWork += new DoWorkEventHandler(FillCustomers); 
    customerWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(customerWorker_RunWorkerCompleted); 
    FillCustomers(null, null); 

} 

Quando faccio un cambio di indice che chiama una BackgroundWorker che chiama il seguente codice:

private void FillCustomers(object sender, DoWorkEventArgs e) 
    { 
     string connectionString = Settings.Default.ProdConnectionString; 
     SqlConnection connection = new SqlConnection(connectionString); 
     SqlCommand SqlCmd = new SqlCommand(); 
     Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait; 


      SqlCmd.CommandType = CommandType.StoredProcedure; 
      SqlCmd.Parameters.Add("@division", SqlDbType.NVarChar).Value = division; 
      SqlCmd.Connection = connection; 
      SqlCmd.CommandText = "sp_GetCustomers"; 
      SqlDataReader reader = null; 
      connection.Open(); 
      reader = SqlCmd.ExecuteReader(); 
      List<string> result = new List<string>(); 
      while (reader.Read()) 
      { 
       result.Add(reader["NAME"].ToString()); 
      } 
      e.Result = result; 


    } 

Il il problema è che non sono in grado di cambiare le selezioni su CboDivision e fare in modo che CboCustomerList cancelli e ricarichi nuovi valori al suo interno. È il modo in cui lego i valori in xaml? Come posso avere una modifica in CboDivision causa una cancellazione di elementi CboCustomerList, quindi l'esecuzione della routine di riempimento?

Attualmente sto Reset del combobox con:

CboCustomerList.SelectedIndex = -1; 

ma questo solo aggiunge la nuova query cbocustomerlist alla fine Ho anche provato

CboCustomerList.Items.Clear() 

ma che semplicemente restituisce un errore di riferimento null dopo la scatola viene riempita e l'utente seleziona un oggetto.

+1

Il 'NullReferenceException' è gettato a causa del l'ultima istruzione nel metodo' FillCustomers' e il fatto che in 'metodo CboDivision_SelectionChanged' che stai chiamando' FillCustomers (null , null) '(il secondo' null' è assegnato al parametro 'e'). In questo modo in realtà non stai usando il lavoratore - per farlo dovresti chiamare invece "customerWorker.RunWorkerAsync()". – Grx70

+0

@ Jac Jacton ha ragione nel dire che il tuo thread di lavoro non è mai stato avviato, o manca del codice? Se in effetti invochi il thread di lavoro, cosa succede nel gestore per il completamento?Piuttosto che impostare ItemsSource su null, hai provato a svuotare la collezione a cui è destinato? – User92

risposta

4

Beh, non ha tutti i post del vostro codice, ma un problema è che non si sta invocando il tuo thread di lavoro.

Sostituire FillCustomers(null, null) con customerWorker.RunWorkerAsync().

private void CboDivision_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    division = CboDivision.SelectedValue.ToString(); 
    CboCustomerList.ItemsSource = null; 

    BackgroundWorker customerWorker = new BackgroundWorker(); 
    customerWorker.DoWork += new DoWorkEventHandler(FillCustomers); 
    customerWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(customerWorker_RunWorkerCompleted); 
    customerWorker.RunWorkerAsync(); // <-- this 
} 

Fammi sapere se questo è utile. Se il problema persiste, invia il resto del codice.

3

Ci sono dettagli del codice che non hai mostrato. Tuttavia, ecco un esempio che funziona: due combo, quello che viene popolato all'inizio e un secondo che viene popolato ogni volta che la selezione cambia nel primo. Si noti che i dati vengono recuperati in un worker in background, proprio come nel tuo caso.

XAML

<Window x:Class="CombosRefresh.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"> 
    <Grid> 
     <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <ComboBox Name="CboDivisions" ItemsSource="{Binding}" Grid.Row="0" Margin="5" /> 
     <ComboBox Name="CboList" ItemsSource="{Binding}" Grid.Row="1" Margin="5" /> 
    </Grid> 
</Window> 

C#

public partial class MainWindow : Window 
    { 
     private BackgroundWorker bw = new BackgroundWorker(); 

     public MainWindow() 
     { 
     InitializeComponent(); 

     CboDivisions.DataContext = new List<string>() { "red", "blue", "green" }; 
     CboDivisions.SelectionChanged += CboDivisions_SelectionChanged; 

     bw.DoWork += bw_DoWork; 
     bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
     } 

     void CboDivisions_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
     var division = CboDivisions.SelectedValue as string; 
     bw.RunWorkerAsync(division); 
     } 

     void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
     CboList.DataContext = e.Result as List<string>; 
     } 

     void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
     var division = e.Argument as string; 

     var r = new Random(); 
     var result = new List<string>(); 

     for(int i = 0; i < r.Next(0, 10); ++i) 
     { 
      result.Add(string.Format("{0} #{1}", division, i+1)); 
     } 

     e.Result = result; 
     } 
    } 
+0

su e.Result = risultato; Viene visualizzato un errore di riferimento null. Inoltre, quali dettagli dovrei mostrare in modo da poter ottenere la risposta? – rigamonk

+0

Ciò significa che non hai copiato il codice che ho mostrato. Ho provato questo prima di postarlo qui. Purtroppo non posso allegare file per mostrarti l'intero progetto, ma non c'è nient'altro tranne questo. –

2

sostituire il codice errato FillCustomers(null, null); con: customerWorker.RunWorkerAsync();