/ / WPF DatVMMB de databinding imbriqué - wpf, liaison de données

Datagrid imbriqué dans la mise à jour MVVM de WPF - wpf, liaison de données

Je suis un débutant au pattern WPF et MVVM. J'ai toujours un problème avec la liaison de données en cas de liaison descendante. Je voudrais relier selectedValues ​​des Combobox dans ma collection Oberservable. J'ai appris qu'il est possible de lier la valeur d'une liste déroulante à une propriété, mais dans ce cas, je voudrais lier une propriété d'une collection et la collection est le parent.

Quelqu'un pourrait-il m'expliquer comment lier les valeurs sélectionnées de la liste déroulante à ma collection d'observables?

J'ai une solution de rechange dans mon esprit pour chacuncombobox une nouvelle propriété dans mon modèle de vue et de collecter toutes les valeurs et de stocker par bouton appuyez sur cette valeur dans ma collection, mais cela me semble faux, car ce n'est pas le comportement de la liaison de données.

MODIFIER Les éléments de liste déroulante sont corrigés à partir de chaque modèle, mais comment puis-je lier la valeur sélectionnée de la liste déroulante à ma propriété de collection?

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

The SelectedValue="{Binding Path=RowEntries}" est faux ou est-ce correct?

EDIT 2

J'ai ajouté une Listview liée à ma collection pour voir si les propriétés sont liées à la valeur sélectionnée de ma liste déroulante, mais est conservée vide.

<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>

J'ai cette solution:

Solution

Mes modèles:

// 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; }
}

Mon 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
}

Mon 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>

Réponses:

1 pour la réponse № 1

Vous devez lier la propriété SelectedValue duComboBoxes aux propriétés CityName et CountryName de l'objet RowEntry et définissez la propriété SelectedValuePath des ComboBoxes sur "Name". Définissez également le paramètre UpdateSourcePropertyTrigger des liaisons sur 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>

Ensuite, les créateurs des propriétés source (CityName et CountryName) seront appelés lorsque vous sélectionnez un élément dans les ComboBoxes.

Si vous souhaitez sélectionner certaines valeurs initialement, vous définissez simplement ces propriétés sur certaines valeurs présentes dans les zones de liste déroulante:

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