工作示例:
我有一个名为groups的表,如下所示:
在查看上图后,我想您可能已经理解主键和外键存在于同一个表中。我认为这就是开发人员所说的循环引用。
在MainWindow.xaml中,我有一个DataGrid,它包含三列,即Group Name,Parent Name,Description。 xaml看起来像:
<Window .......>
<Window.DataContext>
<self:MainWindowViewModel />
</Window.DataContext>
<DataGrid ItemsSource="{Binding Groups}" TabIndex="1">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Group Name" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding GroupName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding GroupName}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Parent" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ParentID, Converter={StaticResource GroupIDToGroupNameConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
SelectedValue="{Binding ParentID}"
SelectedValuePath="GroupID"
DisplayMemberPath="GroupName"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Description" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Description}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</power:PowerDataGrid.Columns>
</power:PowerDataGrid>
</Window>
现在我有一个名为MainWindowViewModel
的ViewModelpublic class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
SampleDBContext sampleDBContext = new SampleDBContext();
Groups = new ObservableCollection<Group>();
GroupsCollection = new ObservableCollection<Group>(from g in sampleDBContext.Groups select g);
}
private ObservableCollection<Group> _groups;
public ObservableCollection<Group> Groups
{
get
{
return _groups;
}
set
{
_groups = value;
OnPropertyChanged("Groups");
}
}
private ObservableCollection<Group> _groupsCollection;
public ObservableCollection<Group> GroupsCollection
{
get
{
return _groupsCollection;
}
set
{
_groupsCollection = value;
OnPropertyChanged("GroupsCollection");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertryName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertryName));
}
}
#endregion
}
GroupIDToGroupName.cs // Converter
public class GroupIDToGroupName : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
SampleDBContext sampleDBContext = new SampleDBContext();
return (from g in sampleDBContext.Groups
where g.GroupID == (int)value
select g.GroupName).FirstOrDefault();
}
else
{
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
SampleDBContext sampleDBContext = new SampleDBContext();
return (from g in sampleDBContext.Groups
where g.GroupName == (string)value
select g.GroupID).FirstOrDefault();
}
}
在App.xaml中:
<self:GroupIDToGroupName x:Key="GroupIDToGroupNameConveerter" />
我的案例(与上面的示例非常相似):
我只想在DataGrid中使用多列ComboBox而不是简单的ComboBox。
我有两张桌子:
现在我完全按照上面提到的代码设置了我的代码。
我添加了一个名为GroupIDAndNameWithCorrespondingEffect的额外类,如:
public class GroupIDAndNameWithCorrespondingEffect : INotifyPropertyChanged
{
private int _groupID;
public int GroupID
{
get
{
return _groupID;
}
set
{
_groupID = value;
OnPropertyChanged("GroupID");
}
}
private string _groupName;
public string GroupName
{
get
{
return _groupName;
}
set
{
_groupName = value;
OnPropertyChanged("GroupName");
}
}
private string _correspondingEffect;
public string CorrespondingEffect
{
get
{
return _correspondingEffect;
}
set
{
_correspondingEffect = value;
OnPropertyChanged("CorrespondingEffect");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我的ViewModel中的更改:
我删除了属性GroupsCollection及其所有引用,并添加了一个名为GroupIDAndNamesWithCorrespondingEffects的新属性,如下所示:
private ObservableCollection<GroupIDAndNameWithCorrespondingEffect> _groupIDAndNamesWithCorrespondingEffects;
public ObservableCollection<GroupIDAndNameWithCorrespondingEffect> GroupIDAndNamesWithCorrespondingEffects
{
get
{
return _groupIDAndNamesWithCorrespondingEffects;
}
set
{
_groupIDAndNamesWithCorrespondingEffects = value;
OnPropertyChanged("GroupIDAndNamesWithCorrespondingEffects");
}
}
在构造函数中:
List<GroupIDAndNameWithCorrespondingEffect> _GroupIDAndNamesWithCorrespondingEffects = (
from g in sampleDBContext.Groups
select new GroupIDAndNameWithCorrespondingEffect
{
GroupID = g.GroupID,
GroupName = g.GroupName,
CorrespondingEffect = g.Effect.Effect1
}
).ToList();
GroupIDAndNamesWithCorrespondingEffects
= new ObservableCollection<GroupIDAndNameWithCorrespondingEffect>(
_GroupIDAndNamesWithCorrespondingEffects.Where
(
u => !GetAllChildren(25)
.Select(x => x.GroupID)
.Contains(u.GroupID)
).ToList()
);
在我的MainWindow.xaml中,我添加了如下资源:
<Window.Resources>
<CollectionViewSource x:Key="GroupNamesWithCorrespondingEffectsCollection" Source="{Binding GroupIDAndNamesWithCorrespondingEffects}" />
</Window.Resources>
Inside Grid的资源:
<Grid.Resources>
<CompositeCollection x:Key="Items">
<ComboBoxItem IsEnabled="False" Background="#FF2A2A2A" Foreground="White">
<Grid TextElement.FontWeight="Bold" >
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition Width="50" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="Group Name" />
<TextBlock Grid.Column="2" Text="Effect" />
</Grid.Children>
</Grid>
</ComboBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource GroupNamesWithCorrespondingEffectsCollection}}" />
</CompositeCollection>
<DataTemplate DataType="{x:Type self:GroupIDAndNameWithCorrespondingEffect}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition Width="50" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="{Binding GroupName}" />
<TextBlock Grid.Column="2" Text="{Binding CorrespondingEffect}" />
</Grid.Children>
</Grid>
</DataTemplate>
</Grid.Resources>
我将ComboBox的ItemsSource更改为ItemsSource =“{DynamicResource Items}”。
问题:
当我运行程序时,ComboBox会正确显示所有项目。此外,还显示带有标题的两列。它工作正常,但当我按 Enter 或 TAB 时,焦点仍然在同一个单元格中,并且comboBox的文本显示GroupIDAndNameWithCorrespondingEffect的命名空间
以下是问题的图像:
示例:
答案 0 :(得分:1)
得到了!!!!
我在Grid中使用key="Items"
声明了资源。因此,当我在DataGrid的ComboBox.SelectedIndex
事件中检查PreviewKeyDown
时,它会给我-1
,因此我的逻辑工作意外。此外,此时我得到ComboBox.Items.Count = 0
。
所以我刚刚改变了资源声明的地方。我的意思是我删除了Grid.Resources Section
并在ComboBox.Resources section
中编写了相同的代码。现在工作正常。现在在PreviewKeyDown of DataGrid
,我得到了预期的SelectedIndex of the ComboBox
以及ComboBox.Items.Count is equal to the Count in Source
。
我不知道为什么会这样?因为我已将其用作DynamicResource
,所以即使它在Grid.Resources部分中声明,我也希望它能够正常工作。
答案 1 :(得分:0)
也许......也许你的组合框只需要IsEditable = false。 IsEditable = True导致组合框显示名称空间而不是文本。
答案 2 :(得分:0)
解决此问题的一种方法是http://www.shujaat.net/2010/08/wpf-editable-combobox-with-datatemplate.html
TextSearch.TextPath="GroupName"
另一种方法是向ComboBox的ItemTemplate提供DataTemplate
<ComboBox ItemTemplate="{StaticResource myDataTemplate}"/>