我有一个DataGrid
,其中包含DataGridTemplateColumn
和ComboBox
。
<DataGrid GridLinesVisibility="All" AutoGenerateColumns="False" ItemsSource="{Binding TestItemCollection}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Test Column">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="150"
HorizontalAlignment="Left"
ItemsSource="{Binding TestChildCollection}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
public ObservableCollection<TestClass> TestItemCollection { get; set; } = new ObservableCollection<TestClass>
{
new TestClass(),
new TestClass(),
new TestClass(),
};
public class TestClass
{
public ObservableCollection<string> TestChildCollection { get; set; } = new ObservableCollection<string>
{
"First test item", "Second test item" , "Third test item" , "Fourth test item"
};
}
当我点击空白行中的ComboBox
时,它显然没有创建我的收藏集的新实例,只提供了一个空白列表。
我必须双击空行空间。
只有这样我才能获得ComboBox
中的数据。
如何通过单击空行来获取Combobox
中的数据?
答案 0 :(得分:1)
我已经找到了一个解决方案,您可以通过以下两个步骤实现所需的功能。
第一步:您应为CellEditingTemplate
指定DataGridTemplateColumn
,并为IsHitTestVisible
设置false
至DataGridTemplateColumn.CellTemplate
。这会强制用户界面在点击DataGridCell
(例如您的ComboBox
)时进入编辑模式,因此会创建新的集合实例。为此,您应首先在TestClass
中定义一个属性,以保留每个ComboBox
的选定值:
public class TestClass
{
public ObservableCollection<string> TestChildCollection { get; set; }
// keeps the selected value of each ComboBox
public string SelectedTestItem { get; set; }
public TestClass()
{
TestChildCollection = new ObservableCollection<string> {"First test item", "Second test item" , "Third test item" , "Fourth test item" };
}
}
然后xaml
的{{1}}应该改变如下:
DataGrid
第二步:正如您在上面的 <DataGrid Grid.Row="0"
SelectionUnit="Cell"
DataGridCell.Selected="DataGridCell_GotFocus"
GridLinesVisibility="All" AutoGenerateColumns="False" ItemsSource="{Binding TestItemCollection}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Test Column">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="150" IsHitTestVisible="False"
HorizontalAlignment="Left"
ItemsSource="{Binding TestChildCollection}"
SelectedItem="{Binding SelectedTestItem}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Width="150"
HorizontalAlignment="Left"
ItemsSource="{Binding TestChildCollection}"
SelectedItem="{Binding SelectedTestItem}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
中所看到的,xaml
设置为SelectionUnit
,也是Cell
的事件处理程序已定义。事件处理程序代码如下:
DataGridCell.Selected
这可以确保每次点击 private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(DataGridCell))
{
DataGrid dataGrid = (DataGrid)sender;
dataGrid.BeginEdit(e);
}
}
时都会进入编辑模式。因此,每次尝试在新创建的DataGridCell
内打开ComboBox
时,只需少点击一次。
答案 1 :(得分:1)
如果您需要在ComboBox
中使用单获取数据,请点击空行,建议您使用Caliburn.Micro将“附加”命令添加到{您DropDownOpened
的事件{1}}。
这里有一个示例:首先是XAML
ComboBox
然后是ViewModel:
<Window x:Class="WpfApplication1.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org"
Title="MainView" Height="600" Width="600"
Name="_window">
<DataGrid GridLinesVisibility="All" AutoGenerateColumns="False" ItemsSource="{Binding TestItemCollection}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Test Column">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="150"
HorizontalAlignment="Left"
ItemsSource="{Binding TestChildCollection}"
cal:Message.Attach="[Event DropDownOpened] = [Action Choose($dataContext)]"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
请在我的示例中考虑public class MainViewModel : Caliburn.Micro.PropertyChangedBase
{
public MainViewModel()
{
TestItemCollection = new ObservableCollection<TestClass>
{
new TestClass(),
new TestClass(),
new TestClass(),
};
}
public void Choose(object data)
{
if (!(data is TestClass))
{
TestItemCollection.Add(new TestClass());
}
}
public ObservableCollection<TestClass> TestItemCollection { get; set; }
}
代码与您编写的代码相同。当然,您必须配置应用程序才能使用Caliburn.Micro(如果您不知道如何操作,可以阅读documentation)。
如果您不想(或可能不能)使用Caliburn.Micro,您可以使用System.Windows.Interactivity库获得相同的结果(请参阅下面的编辑)。
尝试代码:只需单击一下,即可自动创建新行。 我希望它可以帮到你。
修改强> 使用System.Windows.Interactivity
的替代解决方案如果您不能使用Caliburn.Micro,您只需要以这种方式修改MainView XAML:
TestClass
如您所见,我刚刚添加了对 Microsoft.Expression.Interactions 和 System.Windows.Interactivity 库的引用。然后我向<Window x:Class="WpfApplication1.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
Title="MainView" Height="600" Width="600"
Name="_window">
<DataGrid GridLinesVisibility="All" AutoGenerateColumns="False" ItemsSource="{Binding TestItemCollection}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Test Column">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="150"
HorizontalAlignment="Left"
ItemsSource="{Binding TestChildCollection}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DropDownOpened">
<ei:CallMethodAction MethodName="ChooseWithInteraction"
TargetObject="{Binding ElementName=_window, Path=DataContext}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
添加了EventTrigger和CallMethodAction。
现在在ComboBox
中,您可以将MainViewModel
方法替换为Choose
方法(当然您也可以将其添加到代码中):
ChooseWithInteraction
通过这种方式,您可以获得与我的第一个解决方案相同的行为,但不使用Caliburn。