在 Tab 和 Datagrid 上正确绑定 WPF(Collection inside Collection)
Correct Binding in WPF (Collection inside Collection) on Tab and Datagrid
我想在多个选项卡上使用不同的数据网格,但我在正确绑定方面遇到问题。
每个 TabEntry 都有一个 DataGridEntry 集合。
显示选项卡项(Tab1 和 Tab2)但 DataGridEntries 的绑定不正确。
TabEntry.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace TabControlTest
{
public class TabEntry : INotifyPropertyChanged
{
public TabEntry()
{
DataGridEntries = new ObservableCollection<DataGridEntry>();
}
public string Description { get; set; }
public ObservableCollection<DataGridEntry> DataGridEntries{get;set;}
public event PropertyChangedEventHandler PropertyChanged;
}
public class DataGridEntry : INotifyPropertyChanged
{
public string Description { get; set; }
public string Value { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
ObservableCollection<TabEntry> Tabs = new ObservableCollection<TabEntry>();
TabEntry tab1 = new TabEntry();
tab1.Description = "Tab1";
DataGridEntry data1 = new DataGridEntry();
data1.Description = "Tab1 Description 1";
data1.Value = "Tab1 Value 1";
DataGridEntry data2 = new DataGridEntry();
data2.Description = "Tab1 Description 2";
data2.Value = "Tab1 Value 2";
tab1.DataGridEntries.Add(data1);
tab1.DataGridEntries.Add(data2);
TabEntry tab2 = new TabEntry();
tab2.Description = "Tab2";
DataGridEntry data3 = new DataGridEntry();
data1.Description = "Tab2 Description 1";
data1.Value = "Tab1 Value 1";
DataGridEntry data4 = new DataGridEntry();
data2.Description = "Tab2 Description 2";
data2.Value = "Tab1 Value 2";
tab2.DataGridEntries.Add(data3);
tab2.DataGridEntries.Add(data4);
Tabs.Add(tab1);
Tabs.Add(tab2);
this.DataContext = Tabs;
InitializeComponent();
}
}
Tabs 是一个包含 tabEntries 的集合(classTabEntry)
每个 TabEntry 都有一个带有 DataGridEntries(class DataGridEntry) 的集合
如何在 xaml 中正确绑定到这些集合?
<Window x:Class="TabControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabControlTest"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl x:Name="tabControl1" ItemsSource="{Binding}" TabStripPlacement="Left" HorizontalAlignment="Left" Height="242" Margin="10,10,0,0" VerticalAlignment="Top" Width="358">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}"></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding DataGridEntries}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Description}"></DataGridTextColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
我有以下输出:
内容未正确映射到 TabControl 和 DataGrid。
Tab2 上的 Datagrid 是空白的
您的成员 DataGridEntries
必须是 属性 才能用于绑定:
public class TabEntry : INotifyPropertyChanged
{
public TabEntry()
{
DataGridEntries = new ObservableCollection<DataGridEntry>();
}
public string Description { get; set; }
public ObservableCollection<DataGridEntry> DataGridEntries { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
旁注: 仅实现 INotifyPropertyChanged
是不够的 - 您还需要在 getter 方法中调用事件。实施 getters 或使用例如Fody...
这里是你正在尝试做的更清晰的实现
Xaml
<Window x:Class="WpfApplication34.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication34="clr-namespace:WpfApplication34"
Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid>
<TabControl x:Name="tabControl1" ItemsSource="{Binding Tabs}" TabStripPlacement="Left" HorizontalAlignment="Left" Height="242" Margin="10,10,0,0" VerticalAlignment="Top" Width="358">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" ></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding DataGridEntries}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Desription}"></DataGridTextColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Grid>
和代码隐藏:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<TabEntry> _tabs ;
public ObservableCollection<TabEntry> Tabs
{
get
{
return _tabs;
}
set
{
if (_tabs == value)
{
return;
}
_tabs = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
Tabs = new ObservableCollection<TabEntry>()
{
new TabEntry()
{
Description = "Tab1",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
Description = "Tab1 Description 1",
Value = "Tab1 Value 1"
},
new DataGridEntry()
{
Description = "Tab1 Description 2",
Value = "Tab1 Value 2"
}
}
},
new TabEntry()
{
Description = "Tab2",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
Description = "Tab2 Description 1",
Value = "Tab2 Value 1"
},
new DataGridEntry()
{
Description = "Tab2 Description 2",
Value = "Tab2 Value 2"
}
}
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class TabEntry : INotifyPropertyChanged
{
private String _description;
public String Description
{
get
{
return _description;
}
set
{
if (_description == value)
{
return;
}
_description = value;
OnPropertyChanged();
}
}
public ObservableCollection<DataGridEntry> DataGridEntries { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class DataGridEntry : INotifyPropertyChanged
{
private String _description;
public String Description
{
get
{
return _description;
}
set
{
if (_description == value)
{
return;
}
_description = value;
OnPropertyChanged();
}
}
private String _value;
public String Value
{
get
{
return _value;
}
set
{
if (_value == value)
{
return;
}
_value = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
我想在多个选项卡上使用不同的数据网格,但我在正确绑定方面遇到问题。
每个 TabEntry 都有一个 DataGridEntry 集合。 显示选项卡项(Tab1 和 Tab2)但 DataGridEntries 的绑定不正确。
TabEntry.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace TabControlTest
{
public class TabEntry : INotifyPropertyChanged
{
public TabEntry()
{
DataGridEntries = new ObservableCollection<DataGridEntry>();
}
public string Description { get; set; }
public ObservableCollection<DataGridEntry> DataGridEntries{get;set;}
public event PropertyChangedEventHandler PropertyChanged;
}
public class DataGridEntry : INotifyPropertyChanged
{
public string Description { get; set; }
public string Value { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
ObservableCollection<TabEntry> Tabs = new ObservableCollection<TabEntry>();
TabEntry tab1 = new TabEntry();
tab1.Description = "Tab1";
DataGridEntry data1 = new DataGridEntry();
data1.Description = "Tab1 Description 1";
data1.Value = "Tab1 Value 1";
DataGridEntry data2 = new DataGridEntry();
data2.Description = "Tab1 Description 2";
data2.Value = "Tab1 Value 2";
tab1.DataGridEntries.Add(data1);
tab1.DataGridEntries.Add(data2);
TabEntry tab2 = new TabEntry();
tab2.Description = "Tab2";
DataGridEntry data3 = new DataGridEntry();
data1.Description = "Tab2 Description 1";
data1.Value = "Tab1 Value 1";
DataGridEntry data4 = new DataGridEntry();
data2.Description = "Tab2 Description 2";
data2.Value = "Tab1 Value 2";
tab2.DataGridEntries.Add(data3);
tab2.DataGridEntries.Add(data4);
Tabs.Add(tab1);
Tabs.Add(tab2);
this.DataContext = Tabs;
InitializeComponent();
}
}
Tabs 是一个包含 tabEntries 的集合(classTabEntry) 每个 TabEntry 都有一个带有 DataGridEntries(class DataGridEntry) 的集合 如何在 xaml 中正确绑定到这些集合?
<Window x:Class="TabControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabControlTest"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl x:Name="tabControl1" ItemsSource="{Binding}" TabStripPlacement="Left" HorizontalAlignment="Left" Height="242" Margin="10,10,0,0" VerticalAlignment="Top" Width="358">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}"></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding DataGridEntries}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Description}"></DataGridTextColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
我有以下输出:
内容未正确映射到 TabControl 和 DataGrid。
Tab2 上的 Datagrid 是空白的
您的成员 DataGridEntries
必须是 属性 才能用于绑定:
public class TabEntry : INotifyPropertyChanged
{
public TabEntry()
{
DataGridEntries = new ObservableCollection<DataGridEntry>();
}
public string Description { get; set; }
public ObservableCollection<DataGridEntry> DataGridEntries { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
旁注: 仅实现 INotifyPropertyChanged
是不够的 - 您还需要在 getter 方法中调用事件。实施 getters 或使用例如Fody...
这里是你正在尝试做的更清晰的实现 Xaml
<Window x:Class="WpfApplication34.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication34="clr-namespace:WpfApplication34"
Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid>
<TabControl x:Name="tabControl1" ItemsSource="{Binding Tabs}" TabStripPlacement="Left" HorizontalAlignment="Left" Height="242" Margin="10,10,0,0" VerticalAlignment="Top" Width="358">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" ></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding DataGridEntries}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Desription}"></DataGridTextColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Grid>
和代码隐藏:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<TabEntry> _tabs ;
public ObservableCollection<TabEntry> Tabs
{
get
{
return _tabs;
}
set
{
if (_tabs == value)
{
return;
}
_tabs = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
Tabs = new ObservableCollection<TabEntry>()
{
new TabEntry()
{
Description = "Tab1",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
Description = "Tab1 Description 1",
Value = "Tab1 Value 1"
},
new DataGridEntry()
{
Description = "Tab1 Description 2",
Value = "Tab1 Value 2"
}
}
},
new TabEntry()
{
Description = "Tab2",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
Description = "Tab2 Description 1",
Value = "Tab2 Value 1"
},
new DataGridEntry()
{
Description = "Tab2 Description 2",
Value = "Tab2 Value 2"
}
}
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class TabEntry : INotifyPropertyChanged
{
private String _description;
public String Description
{
get
{
return _description;
}
set
{
if (_description == value)
{
return;
}
_description = value;
OnPropertyChanged();
}
}
public ObservableCollection<DataGridEntry> DataGridEntries { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class DataGridEntry : INotifyPropertyChanged
{
private String _description;
public String Description
{
get
{
return _description;
}
set
{
if (_description == value)
{
return;
}
_description = value;
OnPropertyChanged();
}
}
private String _value;
public String Value
{
get
{
return _value;
}
set
{
if (_value == value)
{
return;
}
_value = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}