具有空行的用户可编辑数据网格,即使 observableCollection 为空

User editable datagrid with empty row, even if observableCollection is empty

我正在使用一个数据网格,通过 TwoWay 绑定绑定到一个 observablecollection。 我的目标是,用户从一个空集合开始生成一个数据列表。 所以我启用了 CanUserAddRow 选项。

在代码中,我使用以下代码生成可观察集合:

private ObservableCollection<Ticket> idlessTicketList = new ObservableCollection<Ticket>();

由 ObservableCollection 组成的 Ticket class 如下所示:

public class Ticket
{
    public Ticket() { }

    public bool ticketUsed { get; set; }
    public string ticketNumber { get; set; }
    public string ticketCustomer { get; set; }
    public string ticketText { get; set; }
    public double ticketTime { get; set; }
    public Decimal ticketTypeNr { get; set; }
    public string ticketTypeText { get; set; }

}

在 MainWindow 方法中,我将 Datagrid 的 itemSource 设置为我的 ObservableCollection:

public MainWindow()
{

    InitializeComponent();
    gridIdlessTickets.ItemsSource = idlessTicketList;

}

我现在的问题是,启动时不显示用于添加新行的空行。 如果我通过代码 myGridd.Add(row) 添加新行,则空行会正确显示并且一切正常。

必须如何初始化 ObservableCollection 并正确引用 itemSource? 初始化 itemSource 的最佳位置在哪里?

提前致谢

这应该适合你。让我知道是否有帮助:

XAML:

    <Window>
      <Grid>
        <Datagrid ItemsSource="{Binding idlessTicketList }" SelectionMode="Single" SelectionUnit="Cell" IsReadOnly="False" 
                  CanUserAddRows="True" CanUserDeleteRows="False" AutoGenerateColumns="False">

        //ColumnDefinition...etc
                <DataGridTextColumn Header="TicketNumber" Binding="{Binding TicketNumber}"  />
                <DataGridTextColumn Header="TicketCustomer" Binding="{Binding TicketCustomer}"
        </Datagrid>
<Button name="ThisIsYourUpdateButton" Command="{Binding UpdateMyTicket}" Width="200" Content="Update me now"/>
      </Grid>
    </Window>

代码隐藏 (.xaml.cs):

public MainWindow()
{

    InitializeComponent(); //parses the XAML...
    DataContext = new MainWindowViewModel(); //outsources the view code to the    
    //"controller" to make the view only display and nothing else...

}

视图模型:(MainWindowViewModel.cs)

        using System;
        using System.Collections.ObjectModel;
        using System.ComponentModel;
        using System.Windows;

        namespace YourNameSpace
        {
            public class MainWindowViewModel : INotifyPropertyChanged
            {
                public ICommand UpdateMyTicket => new DelegateCommand<object>(ExecuteUpdateTicket);
                public Ticket TicketInstance {get;set;}
                public event PropertyChangedEventHandler PropertyChanged;
                public virtual void OnPropertyChanged(string propertyName)
                {
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    }
                }

                private ObservableCollection<Ticket> _idlessTicketList;
                public ObservableCollection<Ticket> idlessTicketList
                {
                    get { return _idlessTicketList; }
                    set
                    {
                        _idlessTicketList = value;
                        OnPropertyChanged("idlessTicketList");
                    }
                }

                //Constructor
                public MainWindowViewModel()
                {
                    idlessTicketList = new ObservableCollection<Ticket>();
                }
                public void ExecuteUpdateTicket(obj param)
                {
                  //if the button is clicked you update your Ticket class properties here!
                }
             }
          }

像这样添加DelegateCommand.csclass:

    using System;

namespace YourNamespaceName 
{ 
    public class DelegateCommand<T> : System.Windows.Input.ICommand
    {
        private readonly Predicate<T> _canExecute;
        private readonly Action<T> _execute;

        public DelegateCommand(Action<T> execute)
            : this(execute, null)
        {
        }

        public DelegateCommand(Action<T> execute, Predicate<T> canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute == null)
                return true;

            return _canExecute((parameter == null) ? default(T) : (T)Convert.ChangeType(parameter, typeof(T)));
        }

        public void Execute(object parameter)
        {
            _execute((parameter == null) ? default(T) : (T)Convert.ChangeType(parameter, typeof(T)));
        }

        public event EventHandler CanExecuteChanged;
        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }
}

使用单独的视图模型 Class 初始化 observablecollection,空行显示正确。 但是数据不再更新了。 这是我所做的:

我添加了新的 class 作为新的命名空间

xmlns:vm="clr-namespace:nsMainWindowViewModel"

绑定是这样写的:

<DataGrid ItemsSource="{Binding Path=idlessTicketList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  AutoGenerateColumns="False" >
       <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Mode=TwoWay, Path=ticketCustomer, UpdateSourceTrigger=PropertyChanged}"/>
            <DataGridTextColumn Binding="{Binding Mode=TwoWay, Path=ticketText, UpdateSourceTrigger=PropertyChanged}"/>
            <DataGridTextColumn Binding="{Binding Mode=TwoWay, Path=ticketTime, UpdateSourceTrigger=PropertyChanged, StringFormat=\{0:n2\}}"/>
       </DataGrid.Columns>
</Datagrid>

使用此实现,PropertyChangedEventHandler 在应用程序启动时被调用,但元素更改时不会被调用。

绑定必须怎么写? 对于我尝试过的数据网格:

{Binding Path=(idlessTicketList), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
{Binding Path=(vm:idlessTicketList), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
{Binding Path=(vm:MainWindowViewModel.idlessTicketList), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}

对于我试过的专栏;

{Binding Mode=TwoWay, Path=ticketCustomer, UpdateSourceTrigger=PropertyChanged}
{Binding Mode=TwoWay, Path=(vm:ticketCustomer), UpdateSourceTrigger=PropertyChanged}
{Binding Mode=TwoWay, Path=(vm:MainWindowViewModel.ticketCustomer), UpdateSourceTrigger=PropertyChanged}

调试时,我可以看到最初调用了 PropertyChange 方法,但在编辑单个元素后没有调用。

必须如何定义绑定以更新另一个命名空间中的 te observableCollection?

提前致谢