首次发布。我是C#和WPF的新手。我花了超过15个小时来尝试解决这个问题,而我将退出并开始使用Windows Forms。我有一个(当前)三列的DataGrid,但是只有两列对此很重要,即Type和Subtype。我从XML文件中填充了大约15种类型,每种类型都有2-15个子类型。我正在尝试根据第一列中选择的内容来过滤(或填充)第二列。
我尝试在第二列上使用DynamicResource,但在下一行将覆盖它,并清除第一行的选择。我对绑定没有足够的了解,无法知道如何使它们特定于行。我已经在C#端创建了一个列表和一个集合,其中填充了所选类型的每个子类型(以及为每个可能的Type填充的另一对,甚至在我的类型集合中嵌入了一个子类型集合),但是我可以t弄清楚如何将其中任何一个添加到第二列的组合框项目源中,而不在每一行中都显示它们。
XAML:
<DataGridComboBoxColumn Header="Type"
ItemsSource="{DynamicResource UnitTypeSource}"
SelectedValuePath="TypeString"
SelectedItemBinding="{Binding Path=TypeString, NotifyOnTargetUpdated=True}"
DisplayMemberPath="TypeString"
x:Name="colTypeUnit"/>
<DataGridTemplateColumn Header="Subtype">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding DataContext.AllSubtypes, RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
DisplayMemberPath="Name"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
希望对您有所帮助,甚至只是作为参考。
答案 0 :(得分:0)
使用DataGrid和ComboBoxes可能会很快变得有点复杂,因此让我们一次跨一步,并进行一些解释。我已经为您提供了代码段中的完整类。
首先,我将坚持使用MVVM模型,并使用model-view-viewmmodel将数据绑定到DataGrid。视图模型将包含Type
和SubType
值列表以及行列表。我将将此行的模型类称为TypeModel
:
public class TypeModel
{
public string Type { get; set; }
public string SubType { get; set; }
}
我不知道您如何确定SubType
对给定的Type
有效,但是对于本示例,我将使用字典在视图模型中设置关系。
因此我们的视图模型可能类似于:
public class MainWindowViewModel
{
public ObservableCollection<TypeModel> Collection { get; set; }
public ObservableCollection<string> Type { get; set; }
public Dictionary<string, List<string>> SubTypeCollection { get; set; }
public MainWindowViewModel()
{
Collection = new ObservableCollection<TypeModel>();
TypeCollection = new ObservableCollection<string>()
{
"Type 1","Type 2","Type 3"
};
SubTypeCollection = new Dictionary<string, List<string>>()
{
{
TypeCollection[0], new List<string>()
{
"Type 1 - Sub type 0",
"Type 1 - Sub type 1"
}
},
{
TypeCollection[1], new List<string>()
{
"Type 2 - Sub type 0",
"Type 2 - Sub type 1",
"Type 2 - Sub type 2",
"Type 3 - Sub type 3",
}
},
{
TypeCollection[2], new List<string>()
{
"Type 3 - Sub type 0",
"Type 3 - Sub type 1",
"Type 3 - Sub type 2",
}
}
};
}
}
现在让我们设置(初始)视图(稍后将添加到该视图):
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow"
Width="600"
Height="500">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<DataGrid
AutoGenerateColumns="False"
ItemsSource="{Binding Collection}">
<DataGrid.Columns>
<DataGridComboBoxColumn
Header="Type"
SelectedItemBinding="{Binding Type, UpdateSourceTrigger=PropertyChanged}"> <!-- property changed so we get the change right after we select-->
<DataGridComboBoxColumn.ElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn
Header="Sub Type"
SelectedItemBinding="{Binding SubType}">
<!-- How do we bind to the ItemSource based on the selected type?-->
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
所以您的基本问题是如何填写该注释掉的部分。
执行此操作的方法可能很多,在我看来,最简单的方法是使用带有两个绑定的IMultiValueConverter
:
Type
字符串TypeCollection
所以该类看起来像这样(您真的可以将其用于所有string
至list<string>
的转换):
public class TypeToSubTypesConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null) return null;
if (values[0] == null || values[0] == DependencyProperty.UnsetValue) return null;
var type = values[0].ToString();
if (values[1] == null || values[1] == DependencyProperty.UnsetValue) return null;
var subTypeList = values[1] as Dictionary<string, List<string>>;
if (subTypeList == null) return null;
return subTypeList[type];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
现在最后的步骤是:
value
的每个setter
的{{1}}属性添加多重绑定因此,完整的.xaml如下所示:
ItemsSource