WPF MVVM数据绑定嵌套数据网格

时间:2017-01-10 15:28:51

标签: wpf data-binding

我是WPF和MVVM模式的初学者。在后向绑定的情况下,我仍然存在数据绑定问题。我想将Comboboxes的selectedValues绑定到我的Oberservable Collection中。我学到了可以将组合框的值绑定到属性,但在这种情况下,我想绑定到集合的属性,集合是父。

有人可以解释一下如何将组合框选择值绑定到我的observablecollection中吗?

我有一个解决方法,在我的viewmodel中为每个组合框创建一个新属性并收集所有值并按下按钮按下这个值到我的集合中,但这对我来说似乎错了,因为这不是数据绑定的行为

编辑从每个模型中填充组合框项目,但我如何将组合框的选定值绑定到我的集合属性?

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

The SelectedValue="{Binding Path=RowEntries}"错了或这是正确的吗?

编辑2

我添加了一个Listview绑定到我的集合,看看,如果属性绑定到我的组合框的selectedvalue,但是保持为空。

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

我有这个解决方案:

Solution

我的模特:

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

我的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
}

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

1 个答案:

答案 0 :(得分:1)

您应该将ComboBoxes的SelectedValue属性绑定到RowEntry对象的CityName和CountryName属性,并将ComboBoxes的SelectedValuePath属性设置为&#34; Name&#34;。还要将绑定的UpdateSourcePropertyTrigger设置为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>

然后,当您在组合框中选择项目时,将调用源属性(CityName和CountryName)的setter。

如果您想最初选择一些值,只需将这些属性设置为组合框中存在的某些值:

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