WPF DataGrid单击以创建新项

时间:2015-10-15 10:10:56

标签: wpf mvvm combobox datagrid datagridtemplatecolumn

我有一个DataGrid,其中包含DataGridTemplateColumnComboBox

<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时,它显然没有创建我的收藏集的新实例,只提供了一个空白列表。

enter image description here

我必须双击空行空间。

enter image description here

只有这样我才能获得ComboBox中的数据。

enter image description here

如何通过单击空行来获取Combobox中的数据?

2 个答案:

答案 0 :(得分:1)

我已经找到了一个解决方案,您可以通过以下两个步骤实现所需的功能。

第一步:您应为CellEditingTemplate指定DataGridTemplateColumn,并为IsHitTestVisible设置falseDataGridTemplateColumn.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> 添加了EventTriggerCallMethodAction

现在在ComboBox中,您可以将MainViewModel方法替换为Choose方法(当然您也可以将其添加到代码中):

ChooseWithInteraction

通过这种方式,您可以获得与我的第一个解决方案相同的行为,但不使用Caliburn。