【问题标题】:WPF MVVM Databinding Nested DatagridWPF MVVM 数据绑定嵌套数据网格
【发布时间】:2017-01-10 15:28:50
【问题描述】:

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

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

我有一个解决方法,可以在我的视图模型中为每个组合框创建一个新属性并收集所有值并通过按钮将这些值存储到我的集合中,但这对我来说似乎是错误的,因为这不是数据绑定的行为.

EDIT 组合框项已从每个模型中更正填充,但我如何将组合框的 selectedvalue 绑定到我的集合属性?

<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,以查看属性是否绑定到我的组合框的选定值,但保持为空。

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

我有这个解决方案:

我的模特:

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

我的视图模型:

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
}

我的用户界面:

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

【问题讨论】:

  • 您的问题是什么?同时显示 XAML 标记。
  • 抱歉,输入时连接中断。请查看我的完整帖子
  • 您的RelativeSource 似乎不正确,您可以试试这个RelativeSource={RelativeSource AncestorType={x:Type Window}}
  • 避免误会。添加开始 Rowentries 集合为空,集合应由组合框选择的值填充。 @Kim 我试过了,但这给了我语法错误。

标签: wpf data-binding


【解决方案1】:

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

然后,当您在 ComboBoxes 中选择一个项目时,将调用源属性(CityName 和 CountryName)的设置器。

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

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

【讨论】:

  • 非常感谢。我明天可以对其进行测试,直到那时我对您的解决方案有疑问,以便更好地理解。 SelectedValuePath 对我来说很有意义,但为什么我必须使用 UpdateSourceTrigger=PropertyChanged 才能使用?我以为事件被提升到后面的mvvm模式了。
  • UpdateSourceTrigger 属性控制何时设置源属性:msdn.microsoft.com/en-us/library/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
  • 1970-01-01
  • 2014-01-29
  • 2012-12-10
  • 1970-01-01
  • 2015-05-24
相关资源
最近更新 更多