用于分层信息的WPF DataGrids

时间:2013-07-23 22:25:57

标签: c# wpf xaml

我的应用包含ObservableCollection<Foo>,而Foo又包含ObservableCollection<Bar>。我想要一对datagrids,一个显示应用程序中Foo个对象的集合,另一个显示Bar中当前在第一个数据网格中选择的Foo个对象的集合(我希望能够在两个数据网格中添加,更新和删除条目。

到目前为止,我已经获得了以下XAML:

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" ItemsSource="{Binding Foos}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Foo Name" Binding="{Binding Name}" Width="Auto" IsReadOnly="False" />
            </DataGrid.Columns>
        </DataGrid>
        <GridSplitter HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext" Width="5" Background="Gray" />
        <DataGrid Grid.Column="2">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Bar Name" Width="Auto" IsReadOnly="False"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

以下代码:

using System;
using System.Windows;
using System.Collections.ObjectModel;

namespace Test
{
    public class Foo
    {
        static int _nextId;
        public int Id { get; private set; }
        public String Name { get; set; }
        public ObservableCollection<Bar> Bars { get; set; }
        public Foo()
        {
            Id = _nextId++;
            Name = String.Empty;
            Bars = new ObservableCollection<Bar>();
        }
    }

    public class Bar
    {
        static int _nextId;
        public int Id { get; private set; }
        public String Name { get; set; }
        public Bar()
        {
            Id = _nextId++;
            Name = String.Empty;
        }
    }
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<Foo> Foos { get; set; }
        public MainWindow()
        {
            Foos = new ObservableCollection<Foo>();
            Foo newFoo;
            for (int index = 0; index < 5; ++index)
            {
                newFoo = new Foo();
                newFoo.Name = String.Format("Foo {0}", index);
                Foos.Add(newFoo);
            }
            InitializeComponent();
            DataContext = this;
        }
    }
}

显然我还没有绑定第二个DataGrid,因为我没有最简单的想法怎么做!我能找到的所有例子都假设我绑定DataTables,而不是自定义对象,并绑定到DataTables上的关系。我真的不明白那么好的约束力。谁能告诉我如何绑定第二张桌子?

(是的,如果你已经看过我最近的其他问题了,那么在早期没有得到很好的帮助后,我会给WPF另一个镜头。)

提前致谢。

2 个答案:

答案 0 :(得分:1)

使用绑定到元素
将顶部网格命名为gridTop

DataContext="{Binding ElementName=gridTop, Path=SelectedItem.Bars}"

答案 1 :(得分:1)

嗨如果您想要可编辑网格,首先必须实现INotifyPropertyChanged

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}

public class ViewModel 
{
    public ViewModel()
    {
        Foos = new ObservableCollection<Foo>();
    }

    public ObservableCollection<Foo> Foos { get; set; }
}

public class Foo : INotifyPropertyChanged
{
    static int _nextId;
    public int Id { get; private set; }
    public ObservableCollection<Bar> Bars { get; set; }
    public Foo()
    {
        Id = _nextId++;
        Name = String.Empty;
        Bars = new ObservableCollection<Bar>();
    }
    private string name;

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            Notify("Name");
        }
    }

    private void Notify(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

}

public class Bar : INotifyPropertyChanged
{
    static int _nextId;
    public int Id { get; private set; }
    public Bar()
    {
        Id = _nextId++;
        Name = String.Empty;
    }

    private string name;

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            Notify("Name");
        }
    }

    private void Notify(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

在xaml中绑定第一个网格是正确的,对于第二个网格,您可以使用ElementName将ItemsSource设置为第一个网格的selectedItem

<DataGrid Grid.Column="2" ItemsSource="{Binding ElementName=gridTop, Path=SelectedItem.Bars}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Bar Name" Binding="{Binding Name}" Width="Auto" IsReadOnly="False"/>
        </DataGrid.Columns>
    </DataGrid>