我目前有一个带有 3 个组合框的列表视图框。我正在用sql数据库中填充它们。对于每一行,我想让第三个组合框根据第二个组合框的选定值更改其内容。
组合框将是:cmbx1(员工[杰克,吉尔,汤姆,丽莎](,cmbx2(产品[钢笔,铅笔,订书机](,cmbx3(颜色 - 将根据产品可用的颜色动态(
产品和颜色选择:笔[红色,蓝色,黑色]; 铅笔[黑色,橙色,红色];订书机[粉红色,蓝绿色,紫色,棕色]
如果对于 Row1,用户选择笔,则只有该产品的可用颜色才会列在该行的颜色组合框中。下一行可能根据所选产品具有不同的颜色选项。
这是否可能,或者我应该找到另一种方法来达到结果?
这是目前拥有的...
<ListView.View>
<GridView>
<GridViewColumn Header="Employee" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding lStrEmployee}" Width="120" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding lStrProduct}" Width="120" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Color" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding lStrColor}" Width="120" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView.View>
代码隐藏
List<Int32> liEmployee = new List<Int32>();
List<string> lsEmployee = new List<string>();
List<Int32> liProduct = new List<Int32>();
List<string> lsProduct = new List<string>();
List<Int32> liColor = new List<Int32>();
List<string> lsColor = new List<string>();
SqlConnection conn = new SqlConnection("Data Source=localhost\SQLEXPRESS;Initial Catalog=testDB;Persist Security Info=True;User ID=USER;Password=PASSWORD;");//Connect Timeout=900
SqlCommand cmd1 = new SqlCommand("select id,employee from testDB.dbo.dmEmployee where inactive=0", conn);
SqlCommand cmd2 = new SqlCommand("select id,Product from testDB.dbo.tblProductList where inactive=0", conn);
SqlCommand cmd3 = new SqlCommand("select id,Color from testDB.dbo.Color where inactive=0", conn);
conn.Open();
SqlDataReader dr1 = cmd1.ExecuteReader();
while (dr1.Read())
{
liEmployee.Add(dr1.GetInt32(dr1.GetOrdinal("id")));
lsEmployee.Add(dr1.GetString(dr1.GetOrdinal("employee")));
}
conn.Close();
conn.Open();
SqlDataReader dr2 = cmd2.ExecuteReader();
while (dr2.Read())
{
liProduct.Add(dr2.GetInt32(dr2.GetOrdinal("id")));
lsProduct.Add(dr2.GetString(dr2.GetOrdinal("Product")));
}
conn.Close();
conn.Open();
SqlDataReader dr3 = cmd3.ExecuteReader();
while (dr3.Read())
{
liColor.Add(dr3.GetInt32(dr3.GetOrdinal("id")));
lsColor.Add(dr3.GetString(dr3.GetOrdinal("Color")));
}
conn.Close();
List<lvItem> itemFound = new List<lvItem>();
itemFound.Clear();
lvItem puzzlePieces;
for (int cnt = 0; cnt < 10; cnt++)
{
puzzlePieces = new lvItem();
puzzlePieces.lStrEmployee = lsEmployee;
puzzlePieces.lStrDatabase = lsDatabase;
puzzlePieces.lStrProvider = lsProvider;
itemFound.Add(puzzlePieces);
}
list1.ItemsSource = itemFound;
谢谢!
惊讶你没有得到任何问题的答案。也许是因为您似乎没有按照 WPF 的方式做事,或者可能是因为您的要求太多了?
首先要做的是...您需要创建一个数据类型类,该类实现INotifyPropertyChanged
接口,并包含在ListView
的每一行中显示的所有属性。在您的例子中,您需要三个集合和三个选定的项目值。例如,您可以执行以下操作(自己实现INotifyPropertyChanged
接口(:
public class RowData : INotifyPropertyChanged
{
public ObservableCollection<Employee> Employees { get; set; }
public Employee SelectedEmployee { get; set; }
public ObservableCollection<Product> Products { get; set; }
public Product SelectedProduct { get; set; }
public ObservableCollection<Brush> Colours { get; set; }
public Brush SelectedColour { get; set; }
}
请注意使用 Brush
类而不是 Color
结构,这是因为Brush
是一个类,这意味着我们可以绑定到它,也因为它在 WPF 中更主要使用。
每行的每个对象中使用相同的集合并不是最佳选择,但 Colours
集合除外,该集合对于每行可能不同。话虽如此,这正是我要做的,因为我解释起来会更快,你可以在稍后阶段自己改进你的代码:
因此,现在您有了数据类型类,我们需要添加该类型的属性以绑定到ListView
控件。如果您使用的是 MainWindow
的代码隐藏,那么让我们为它创建一个DependencyProperty
:
public static readonly DependencyProperty RowDataProperty = DependencyProperty.
Register("RowData", typeof(ObservableCollection<RowData>), typeof(MainWindow),
new UIPropertyMetadata(new ObservableCollection<RowData>()));
public ObservableCollection<RowData> RowData
{
get { return (ObservableCollection<RowData>)GetValue(RowDataProperty); }
set { SetValue(RowDataProperty, value); }
}
填充集合后,现在可以将其绑定到ListView
控件:
xmlns:Local="clr-namespace:YourWpfApplicationName"
...
<ListView ItemsSource="{Binding RowData, RelativeSource={RelativeSource AncestorType={
x:Type Local:MainWindow}}}">
...
</ListView>
简而言之,RelativeSource Binding
只是查找您在代码隐藏中定义的属性。现在,如何定义ComboBox
应该出现在每个GridViewColumn
中?您需要定义GridViewColumn.CellTemplate
:
<GridViewColumn Header="Employees">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Employees}" SelectedItem="{Binding
SelectedEmployee}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
您需要定义此示例中的其他列。所以这个难题的最后一部分是如何根据其他ComboBox
的选定值更新Colours
ComboBox
的内容?答案就在RowData
类中选定的值属性中:
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
NotifyPropertyChanged(SelectedEmployee);
Colours = GetColours();
}
}
private ObservableCollection<Brush> GetColours()
{
ObservableCollection<Brush> newColours = new ObservableCollection<Brush>();
if (SelectedEmployee.Name == "Some Name" && SelectedProduct.Name ==
"Some Product") newColours.AddRange( new List<Brush>() { Brushes.Red,
Brushes.White, Brushes.Blue } );
else ...
}
有很多方法可以做到这一点,我会把它留给你。你现在应该有一个工作的例子,我现在意识到为什么没有人回答你的问题......对于任何理智的人来说,打字都太多了!在花了这么长时间之后,如果您尝试自己解决您发现的任何小问题,我将不胜感激,并希望对您有所帮助。