/ / WPF MVVM Databinding Zagnieżdżony Datagrid - wpf, binding danych

WPF MVVM Databinding Zagnieżdżone Datagrid - wpf, binding danych

Jestem początkującym w stosunku do WPF i MVVM. Nadal mam problem z wiązaniem danych w przypadku wiązania wstecznego. Chciałbym związać wybrane wartości Comboboxes z moją kolekcją Oberservable. Nauczyłem się, że można powiązać wartość combobox z właściwością, ale w tym przypadku chciałbym powiązać właściwość kolekcji, a kolekcja jest rodzica.

Czy ktoś mógłby mi wyjaśnić, jak powiązać wybrane wartości combobox z moim observablecollection?

Mam w moim umyśle obejście tego problemu dla każdegocombobox nową właściwość w moim viewmodelu i zbierz wszystkie wartości i zapisz przez przycisk wciśnij te wartości do mojej kolekcji, ale wydaje mi się to błędne, ponieważ nie jest to zachowanie związane z wiązaniem danych.

EDYTOWAĆ Elementy comboboxes są poprawione w każdym modelu, ale w jaki sposób mogę powiązać wybraną wartość combobox z moją właściwością kolekcji?

<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Path=DataContext.Cities}"
DisplayMemberPath="Name"
SelectedValue="{Binding Path=RowEntries }"/>

The SelectedValue="{Binding Path=RowEntries}" jest źle, czy to jest poprawne?

EDYTUJ 2

Dodałem widok listy powiązany z moją kolekcją, aby zobaczyć, czy właściwości są powiązane z wybraną wartością mojego combobox, ale są puste.

<ListView ItemsSource="{Binding RowEntries}" BorderBrush="Black" BorderThickness="1">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=CityName}"></TextBlock>
<TextBlock Text="{Binding Path=CountryName}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Mam to rozwiązanie:

Rozwiązanie

Moje modele:

// INPC implemented by Propertychanged.Fody
public class RowEntry : BaseModel
{
public string CityName { get; set; }
public string CountryName { get; set; }
}

// INPC implemented by Propertychanged.Fody
public class City : BaseModel
{
public string Name { get; set; }
}
// INPC implemented by Propertychanged.Fody
public class Country : BaseModel
{
public string Name { get; set; }
}

Mój ViewModel:

public class TestViewModel : ViewModelBase
{
#region properties
// INPC implemented by Propertychanged.Fody
public ObservableCollection<City> Cities { get; set; } = new ObservableCollection<City>();
public ObservableCollection<Country> Countries { get; set; } = new ObservableCollection<Country>();
public ObservableCollection<RowEntry> RowEntries { get; set; } = new ObservableCollection<RowEntry>();
#endregion

#region constructors and destructors

/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public TestViewModel()
{
// Sample Data
var temp = new City { Name = "Rom" };
Cities.Add(temp);
var temp2 = new City { Name = "Sydney" };
Cities.Add(temp2);

var temp3 = new Country { Name = "Italy" };
Countries.Add(temp3);
var temp4 = new Country { Name = "Australia" };
Countries.Add(temp4);

RowEntries.Add(new RowEntry());
}
#endregion
}

Moje Ui:

<StackPanel>
<DataGrid ItemsSource="{Binding RowEntries}" AlternationCount="{Binding Items.Count, RelativeSource={RelativeSource Self}}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding AlternationIndex, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Header="#"/>
<DataGridTemplateColumn Header="City">
<DataGridTemplateColumn.CellTemplate>
<HierarchicalDataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Path=DataContext.Cities}"
DisplayMemberPath="Name"
SelectedValue="{Binding Path=RowEntries }"/>
</HierarchicalDataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Countries">
<DataGridTemplateColumn.CellTemplate>
<HierarchicalDataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Path=DataContext.Countries}"
DisplayMemberPath="Name"/>
</HierarchicalDataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Add Row" Margin="0,0,1797,0"></Button>
</StackPanel>

Odpowiedzi:

1 dla odpowiedzi № 1

Powinieneś powiązać właściwość SelectedValue zComboBoxes do właściwości CityName i CountryName obiektu RowEntry i ustaw właściwość SelectedValuePath elementów ComboBox na "Name". Ustaw również UpdateSourcePropertyTrigger powiązań na PropertyChanged:

<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding AlternationIndex, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Header="#"/>
<DataGridTemplateColumn Header="City">
<DataGridTemplateColumn.CellTemplate>
<HierarchicalDataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Cities}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=CityName, UpdateSourceTrigger=PropertyChanged}"/>
</HierarchicalDataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Countries">
<DataGridTemplateColumn.CellTemplate>
<HierarchicalDataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Countries}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=CountryName, UpdateSourceTrigger=PropertyChanged}"/>
</HierarchicalDataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>

Następnie ustawiające właściwości źródła (CityName i CountryName) będą wywoływane po wybraniu elementu w ComboBoxach.

Jeśli chcesz najpierw wybrać niektóre wartości, po prostu ustaw te właściwości na niektóre wartości, które są obecne w elementach ComboBox:

public TestViewModel()
{
...
RowEntries.Add(new RowEntry() { CityName = "Sydney", CountryName = "Australia" });
}