Ich habe zwei Comboboxen: Kategorien und Typen. Wenn mein Formular anfänglich angezeigt wird, listet ich alle Kategorien und Typen auf, die in der Datenbank vorhanden sind. Für beide Comboboxen füge ich Zeile 0 manuell ein, um den Wert "All" zu haben, so dass sie nicht wählen müssen, wenn sie nicht wollen.XAML-Bindungsprobleme mit verbundenen Comboboxen
Ich habe beide Comboboxen an ReactiveObjects gebunden. Wenn der Benutzer eine Kategorie auswählt, wird die Combobox Typ automatisch mit einer Abfrage neu gefüllt, um nur die für die ausgewählte Kategorie relevanten Typen zusammen mit der hinzugefügten Zeile 0 anzuzeigen.
Wenn der Benutzer eine Kategorie auswählt, führt er die Abfrage ordnungsgemäß aus, gibt die relevanten Typen zurück, fügt die Zeile 0 ordnungsgemäß hinzu und die Combobox wird korrekt ausgefüllt. Bei der XAML-Größe wird jedoch die Zeile 0 nicht ausgewählt, und die rote Umrandung um die Combobox wird hinzugefügt, was auf eine ungültige Auswahl hinweist.
Wenn für die Combobox Type keine Auswahl getroffen wurde und das Formular übergeben wurde, wird der korrekte Wert 0 übergeben. Während also alles richtig funktioniert, kommuniziert die rote Box um die Combobox Typen dem Benutzer, dass sie etwas falsch gemacht haben, und ich kann nicht feststellen, warum der XAML die ausgewählten Werte nicht aufnimmt. Ich habe den Code ausgeführt, ohne dass die Zeile 0 hinzugefügt wurde, und es hat immer noch dasselbe Verhalten, d. H. Die Combobox ist korrekt ausgefüllt, aber es ist keine Zeile ausgewählt und die rote Gliederung wird angezeigt.
XAML für Comboboxen
<ComboBox
Grid.Row="3"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource SimpleComboBox}"
ItemsSource="{Binding Categories}"
SelectedValue="{Binding SearchCriteria.CategoryID}"
SelectedValuePath="ComboValueID"
DisplayMemberPath="ComboDataValue"
/>
<TextBlock
Grid.Row="3"
Grid.Column="2"
Style="{StaticResource NormalTextNarrow}"
Text="Type" VerticalAlignment="Top"
/>
<ComboBox
Grid.Row="3"
Grid.Column="3"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource SimpleComboBox}"
ItemsSource="{Binding Types}"
SelectedValue="{Binding SearchCriteria.TypeId}"
SelectedValuePath="ComboValueID"
DisplayMemberPath="ComboDataValue"
/>
Relevante VM Code
// Definition of SearchCriteria. ResourceItem is a ReactiveObject and
// all of the relevant properties watch for changes in values.
private ResourceItem searchCriteria;
public ResourceItem SearchCriteria
{
get { return searchCriteria; }
set { this.RaiseAndSetIfChanged(ref searchCriteria, value); }
}
// This all happens in my constructor
// Defining Row 0
var b = new GenericCombobox { ComboValueID = 0, ComboDataValue = "All" };
// Populating the comboboxes from the database
Categories = omr.GetKTValues("RES_CATEGORIES");
Types = omr.GetKTValuesRU("RES_TYPES");
// Adding the row 0
Categories.Insert(0, b);
Types.Insert(0, b);
// The form is displayed correctly at this point with the row 0 selected
Problem-Code
// When the user picks a category, this is the method that is invoked:
private void categoryChanged()
{
if (SearchCriteria.CategoryID != 0)
{
Types = rr.GetCategoryTypes(SearchCriteria.CategoryID);
SearchCriteria.TypeId = 0;
}
}
// This runs correctly and returns the relevant Types
public List<GenericCombobox> GetCategoryTypes(int categoryId)
{
string sql = "res.usp_GetCategoryTypes";
var types = new List<GenericCombobox>();
SqlConnection sqlCn = DatabaseCommunication.OpenConnection();
using (SqlCommand cmd = new SqlCommand(sql, sqlCn))
{
// Omitting db stuff for brevity...
try
{
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
types.Add(new GenericCombobox
{
ComboValueID = (int)dr["TypeId"],
ComboDataValue = (string)dr["Type"],
IsSelected = false,
Description = (string)dr["Type"],
ComboDataCode = (string)dr["Type"]
});
}
// More db-stuff omitted
}
// Adding the row 0
var b = new GenericCombobox { ComboValueID = 0, ComboDataValue = "All", IsSelected = false, Description = "All", ComboDataCode = "All" };
types.Insert(0, b);
return types;
}
Aktualisierung mit Zusatzcode
// Object containing the TypeId property
public class ResourceItem : ReactiveObject, ISelectable
{
public int Id { get; set; }
public int? OriginalItemId { get; set; }
// ...many other properties...
private int typeId;
public int TypeId
{
get { return typeId; }
set { this.RaiseAndSetIfChanged(ref typeId, value); }
}
// ...and many more follow...
Wenn ich richtig sehe, setzen Sie die 'Types'-Eigenschaft auf eine leere Liste in KategorieChanged, direkt bevor' Typ' noch eine andere Liste zugewiesen (von rr.GetCategoryTypes zurückgegeben). Warum machst du das? Und wie denkst du, reagiert die Combobox, wenn diese leere Liste die Bindung passiert? – elgonzo
@elgonzo: tbh, es ist nur das Ergebnis meines Versuchens (und Versagens) bei verschiedenen Lösungen. Es ist nicht notwendig für irgendetwas anderes in meinem Code und es hat dasselbe Verhalten, wenn ich es herausnehme. – bassrek
Was passiert, wenn Sie die SearchCriteria.TypeId-Eigenschaft auf 0 oder einen anderen Wert zurücksetzen, nachdem Sie die Types-Eigenschaft neu gefüllt haben? – mm8