【问题标题】:How can I make sure my WPF DataGrid shows at least one row when ItemsSource is empty? (Editable ComboBox cells)当 ItemsSource 为空时,如何确保我的 WPF DataGrid 至少显示一行? (可编辑的组合框单元格)
【发布时间】:2018-01-16 11:07:00
【问题描述】:

我有一个 DataGrid,它允许用户编辑电子设备的属性,例如设备具有哪些输入和输出以绘制示意图。在某些情况下,用户正在编辑以前保存的设备 - 在这种情况下,ItemsSource 将绑定一个已经定义的对象的属性。更多的时候,用户会从头开始创建一个新设备,所以 ItemsSource 将是空的。在这种情况下,我的 DataGrid 是完全空白的,我希望它显示一个空白行。我的单元格由可编辑的组合框组成。

到目前为止,我无法让 DataGrid 显示先前定义的 ItemsSource,以及在 ItemsSource 为空时显示空白行。

XAML:

<DataGrid Grid.Column="0" Grid.ColumnSpan="2"
              Grid.Row="1" Grid.RowSpan="2"
              ScrollViewer.VerticalScrollBarVisibility="Auto"
              ItemsSource="{Binding InputList}">
        <DataGrid.Columns>

            <DataGridTemplateColumn Header="Label" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox IsEditable="True"
                                    Text="{Binding NewLabel}"
                                    ItemsSource="{Binding Label}"
                                    SelectedValue="{Binding SelectedLabel}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Signal" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox IsEditable="True"
                                    Text="{Binding NewSignal}"
                                    ItemsSource="{Binding Signal}"
                                    SelectedValue="{Binding SelectedSignal}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Terminal" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox IsEditable="True"
                                    Text="{Binding NewTerminal}"
                                    ItemsSource="{Binding Terminal}"
                                    SelectedValue="{Binding SelectedTerminal}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

        </DataGrid.Columns>

    </DataGrid>

绑定如下: InputList - 先前定义的设备的结构 {Label, Signal, Terminal} 列表。如果这是一个新设备,将在保存时创建新结构。这个 List(IOStruct) 是我的设备对象的一个​​属性。

NewLabel - 如果之前没有使用过,用户可以键入一个新标签 标签 - 先前定义的标签的主列表(使用自动完成快速添加)

SelectedLabel - 如果用户选择之前定义的标签,这将用于生成新结构

接下来的两列具有类似的绑定,但用于信号类型和终端类型。

在没有定义 InputList 的情况下运行应用程序只会给我一个空白的 DataGrid,我不能用它做任何事情。在这种情况下,我希望有一个空白行。

非常感谢任何帮助或提示以使这项工作和改进我的做法!

【问题讨论】:

  • 这不会破坏目的吗?绑定到集合背后的想法是在 DataGrid 中表示集合,而不需要手动填充列和行的所有麻烦。因此,如果您的列表为空或为空,显然您的 DataGrid 也将为空。我很想知道你为什么想要一个空行?
  • 因为这个窗口也可以用来创建一个新设备,在这种情况下,集合开始时是空的。此外,如果我根本没有定义 ItemsSource 绑定,我不会得到一个空白行,也无法添加行(即使使用 CanUserAddRows="True"
  • 你试过 ItemsSource="{Binding InputList, Mode=TwoWay}" 吗?
  • 是的,这不会改变行为

标签: c# wpf mvvm data-binding wpfdatagrid


【解决方案1】:

你可以试试这样的……

首先在 DataGrid 中添加一个额外的列..

 <DataGridTemplateColumn Header="Display Order" Width="96" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding DisplayOrder}" Margin="0" VerticalAlignment="Center" TextAlignment="Right"
                                 HorizontalAlignment="Stretch" x:Name="txtDisplayOrder"  Tag="{Binding}" 
                                 Loaded="txtDisplayOrder_Loaded" MaxLength="1" Background="Transparent" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

DisplayOrder 字段应该出现在 int 类型的 ItemsSource 中。

Loaded 事件应该是这样的

    private void txtDisplayOrder_Loaded(object sender, RoutedEventArgs e)
    {
        TextBox txt = sender as TextBox;
        ValidationRuleInteger objDisplayOrder = new ValidationRuleInteger("Display Order", true, false);
        if (txt != null && objDisplayOrder != null)
            txt.GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules.Add(objDisplayOrder);

    }

最后类 ValidationRuleInteger 应该如下:

 public class clsValidationRuleInteger :ValidationRule
{
    public string strmsg;
    public bool isRequired;
    public bool? isRegex;
    bool AllowNegativeValues;

    public clsValidationRuleInteger(string strmsg, bool isRequired, bool _AllowNegativeValues)
    {
        this.strmsg = strmsg;
        this.isRequired = isRequired;
        AllowNegativeValues = _AllowNegativeValues;
    }

   public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        throw new NotImplementedException();
    }
}

这应该可以根据您的要求正常工作......

【讨论】:

    猜你喜欢
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2012-11-30
    • 2015-11-07
    • 1970-01-01
    相关资源
    最近更新 更多