如何显示带有组合 box/drop 的 DataGrid 属性 下拉列表,该列表根据另一个文本框 属性 的输入而变化
How to display a DataGrid property with combo box/drop down list that varies according to input of another text box property
我有一个 DataGrid,它绑定到如下所示的具有各种属性的列表。我有 2 个要求正在努力解决。
<DataGrid ItemsSource="{Binding Path=VariedObjectList}"
AutoGeneratingColumn="OnAutoGeneratingColumn" x:Name="dataGridView"
SelectionMode="Single" AutoGenerateColumns="true" CanUserAddRows="true" CanUserDeleteRows="true />
- 对于文本框 属性1 中的特定值,属性2 中显示的项目列表应该动态变化。所以,例如,在这里
如果 'Value' 的值为 2,则 'ValueRange' 应显示一个下拉列表,其中包含“2-5”和“5.81-6.6”的项目作为列表项,如果值为 8,则列表更改为 => 7.9-8.8; 8.81-11.2 等如下图所示。
我怎样才能做到这一点?我想保持对整个集合本身的绑定,如上 xaml.
public class VariedObjectList
{
public Modes ModeType { get; set; }
public int Value{ get; set; }
public <dataType??> ValueRange { get; set; } // not sure what should be the type for ValueRange
}
public enum Mode
{
ModeSlow = 0,
ModeFast = 1,
ModeNeutral = 2,
ModeNone = 3
}
- 如果我的 'ModeType' 属性 是 'ModeSlow' 或 'ModeFast' 那么 'ValueRange' 将需要是一个下拉列表。如果 ModeType 是 "ModeNeutral",则 ValueRange 必须接受文本框。我该如何实现?
我按照 Keith 的建议修改了代码,虽然我的大部分更改都有效,但我在以下方面存在问题
(i)我无法使组合框可编辑工作。当我输入时它会产生价值,但一旦我的焦点离开该字段,文本就会消失,并且对于输入的文本,'SelectedValueRange' 永远不会发生绑定。但是当有一个列表并且如果我 select 列表中的任何值时,它将绑定到 'SelectedValueRange' 但不是用于文本输入。
(ii)ModeType 是枚举,当默认输入新行时,我希望它显示 'ModeSlow' 但它是空的。此外,如果我更新一行,所有之前的行也会更新为最新的 value.its 行为很奇怪,但我知道我遗漏了一些东西。
public class VariedObjectList : INotifyPropertyChanged
{
public Mode ModeType { get; set; } = Mode.ModeSlow;
private int val;
public int Value {
get { return val; }
set
{
val = value;
OnPropertyChanged("Value");
SetValueRangeList();
}
}
public List<strings> ValueRange { get; set; }
public string SelectedValueRange {get; set;}
}
以下已更新xaml
我正在为枚举设置 ObjectDataProvider
<Window.Resources>
<ObjectDataProvider x:Key="EnumProvider" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Modes"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources >
<DataGrid x:Name="dataGridView" Grid.Row="0" DataGridCell.Selected="DataGridGotFocus" ItemsSource="{Binding VariedObjectList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False"
CanUserDeleteRows="true" SelectionMode="Single" CanUserAddRows="True" VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header=" ModeType " >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource EnumProvider}}"
SelectedItem="{Binding Path= ModeType
, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value, UpdateSourceTrigger=LostFocus}"/>
<DataGridTemplateColumn Header="ValueRange" >
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedValue="{Binding SelectedValueRange, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path= ValueRange }" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedValueRange, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
有人可以指出我在示例代码中遗漏了什么吗?谢谢。
让我们从 VariedObjectList
class 开始:
由于 ValueRange
将发生变化并且您希望 UI 随之更新,因此 VariedObjectList
将不得不实施 INotifyPropertyChanged Interface.
ValueRange
的类型可以是 int
的任何通用集合。我建议将 属性 声明为 IList<int>
,因为如果需要,它会给您很大的空间来使用不同的集合。
在 ModeType.set
中,随着 PropertyChanged
的增加,您需要创建或检索要为 Mode
显示的值列表,并且然后将该列表分配给 ValueRange
.
现在 DataGrid
:
如果您想根据 ModeType
更改 ValueRange
列的行为,您将不得不放弃 AutoGenerateColumns="true"
相反,您将显式定义<DataGrid.Columns>
标签之间的列。
我会为 ValueRange
列推荐 DataGridTemplateColumn
。 CellEditingTemplate
将包含 ComboBox
和 ItemsSource={Binding ValueRange}
。您可以将 Style
应用于根据 ModeType
的值更改 IsEditable
的 ComboBox
。这将允许您设置用户输入与列表中的任何项目都不匹配的文本的能力。
对于可编辑的 ComboBox
,您将不得不使用 Text
属性。 SelectedValue
和 SelectedItem
仅在从下拉列表中选择项目时有效,在输入自定义文本时无效。
我有一个 DataGrid,它绑定到如下所示的具有各种属性的列表。我有 2 个要求正在努力解决。
<DataGrid ItemsSource="{Binding Path=VariedObjectList}"
AutoGeneratingColumn="OnAutoGeneratingColumn" x:Name="dataGridView"
SelectionMode="Single" AutoGenerateColumns="true" CanUserAddRows="true" CanUserDeleteRows="true />
- 对于文本框 属性1 中的特定值,属性2 中显示的项目列表应该动态变化。所以,例如,在这里 如果 'Value' 的值为 2,则 'ValueRange' 应显示一个下拉列表,其中包含“2-5”和“5.81-6.6”的项目作为列表项,如果值为 8,则列表更改为 => 7.9-8.8; 8.81-11.2 等如下图所示。
我怎样才能做到这一点?我想保持对整个集合本身的绑定,如上 xaml.
public class VariedObjectList
{
public Modes ModeType { get; set; }
public int Value{ get; set; }
public <dataType??> ValueRange { get; set; } // not sure what should be the type for ValueRange
}
public enum Mode
{
ModeSlow = 0,
ModeFast = 1,
ModeNeutral = 2,
ModeNone = 3
}
- 如果我的 'ModeType' 属性 是 'ModeSlow' 或 'ModeFast' 那么 'ValueRange' 将需要是一个下拉列表。如果 ModeType 是 "ModeNeutral",则 ValueRange 必须接受文本框。我该如何实现?
我按照 Keith 的建议修改了代码,虽然我的大部分更改都有效,但我在以下方面存在问题
(i)我无法使组合框可编辑工作。当我输入时它会产生价值,但一旦我的焦点离开该字段,文本就会消失,并且对于输入的文本,'SelectedValueRange' 永远不会发生绑定。但是当有一个列表并且如果我 select 列表中的任何值时,它将绑定到 'SelectedValueRange' 但不是用于文本输入。
(ii)ModeType 是枚举,当默认输入新行时,我希望它显示 'ModeSlow' 但它是空的。此外,如果我更新一行,所有之前的行也会更新为最新的 value.its 行为很奇怪,但我知道我遗漏了一些东西。
public class VariedObjectList : INotifyPropertyChanged
{
public Mode ModeType { get; set; } = Mode.ModeSlow;
private int val;
public int Value {
get { return val; }
set
{
val = value;
OnPropertyChanged("Value");
SetValueRangeList();
}
}
public List<strings> ValueRange { get; set; }
public string SelectedValueRange {get; set;}
}
以下已更新xaml
我正在为枚举设置 ObjectDataProvider
<Window.Resources>
<ObjectDataProvider x:Key="EnumProvider" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Modes"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources >
<DataGrid x:Name="dataGridView" Grid.Row="0" DataGridCell.Selected="DataGridGotFocus" ItemsSource="{Binding VariedObjectList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False"
CanUserDeleteRows="true" SelectionMode="Single" CanUserAddRows="True" VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header=" ModeType " >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource EnumProvider}}"
SelectedItem="{Binding Path= ModeType
, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value, UpdateSourceTrigger=LostFocus}"/>
<DataGridTemplateColumn Header="ValueRange" >
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedValue="{Binding SelectedValueRange, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path= ValueRange }" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedValueRange, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
有人可以指出我在示例代码中遗漏了什么吗?谢谢。
让我们从 VariedObjectList
class 开始:
由于
ValueRange
将发生变化并且您希望 UI 随之更新,因此VariedObjectList
将不得不实施 INotifyPropertyChanged Interface.ValueRange
的类型可以是int
的任何通用集合。我建议将 属性 声明为IList<int>
,因为如果需要,它会给您很大的空间来使用不同的集合。在
ModeType.set
中,随着PropertyChanged
的增加,您需要创建或检索要为Mode
显示的值列表,并且然后将该列表分配给ValueRange
.
现在 DataGrid
:
如果您想根据 ModeType
更改 ValueRange
列的行为,您将不得不放弃 AutoGenerateColumns="true"
相反,您将显式定义<DataGrid.Columns>
标签之间的列。
我会为 ValueRange
列推荐 DataGridTemplateColumn
。 CellEditingTemplate
将包含 ComboBox
和 ItemsSource={Binding ValueRange}
。您可以将 Style
应用于根据 ModeType
的值更改 IsEditable
的 ComboBox
。这将允许您设置用户输入与列表中的任何项目都不匹配的文本的能力。
对于可编辑的 ComboBox
,您将不得不使用 Text
属性。 SelectedValue
和 SelectedItem
仅在从下拉列表中选择项目时有效,在输入自定义文本时无效。