问题在DataGrid组合框C#中添加一行

时间:2020-04-03 17:31:48

标签: c# data-binding combobox datagrid

我正在尝试创建一个以组合框为第一个单元格的数据网格。在其中添加一行时,我有一个奇怪的行为: -如果我在组合框中选择一个项目并跳到下一个单元格,则会清除组合框选择。只有在该行之前没有填写任何内容时,它才会这样做 -存储数据网格中数据的ObervableCollection不会更新。

我在绑定上肯定做错了什么,但是我无法弄清楚是什么...

这是代码(based on this tutorial

GridDataModel

namespace InteractiveGraph.Grid
{
public class DoliInput : ObservableObject, ISequencedObject
{

    private double _speed;
    private string _CTRL;
    private double _destination;
    private double _duration;
    private int _seqNb;



    public string CTRL
    {
        get => _CTRL;
        set
        {
            _CTRL = value;
            OnPropertyChanged("CTRL");
        }
    }
    public double Destination
    {
        get => _destination;
        set
        { 
            _destination = value; 
            OnPropertyChanged("Destination"); 
        }
    }
    public double Speed 
    { 
        get => _speed; 
        set 
        { 
            _speed = value; 
            OnPropertyChanged("Speed"); 
        } 
    }
    public double Duration 
    { 
        get => _duration; 
        set 
        { 
            _duration = value; 
            OnPropertyChanged("Duration"); 
        } 
    }

    public int SequenceNumber 
    { 
        get => _seqNb;
        set
        {
            _seqNb = value;
            OnPropertyChanged("SequenceNumber");
        }
    }

    //THIS EMPETY CONSTRUCTOR IS REALLY IMPORTANT. IT ALLOWS THE DISPLAY OF THE EMPTY ROW AT THE END OF THE DATAGRID 
    public DoliInput(){  }

    public DoliInput(string CTRL, double destination, double speed, double duration)
    {
        this._CTRL = CTRL;
        this._destination = destination;
        this._speed = speed;
        this._duration = duration;
    }
}

GridDataVM

namespace InteractiveGraph.Grid
{
public class DataGridVM : ViewModelBase
{

    void OnDoliCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Update item count
        this.ItemCount = this.DoliInputCollection.Count;

        // Resequence list
        SetCollectionSequence(this.DoliInputCollection);
    }


    private ObservableCollection<DoliInput> _doliInputCollection;
    private int _itemCount;


    public DataGridVM()
    {
        this.Initialise();
    }


    public ObservableCollection<DoliInput> DoliInputCollection
    { 
        get => _doliInputCollection;
        set
        {
            _doliInputCollection = value;
            OnPropertyChanged("DoliInputCollection");
        }
    }

    public int ItemCount 
    { 
        get => _itemCount;
        set 
        { 
            _itemCount = value;
            OnPropertyChanged("ItemCount");
        }
    }
    /// <summary>
    /// Return selected item in the grid
    /// </summary>
    public DoliInput SelectedItem { get; set; }

    /// <summary>
    /// Resets the sequential order of a collection.
    /// </summary>
    /// <param name="targetCollection">The collection to be re-indexed.</param>
    public static ObservableCollection<T> SetCollectionSequence<T>(ObservableCollection<T> targetCollection) where T : ISequencedObject
    {
        // Initialize
        var sequenceNumber = 1;

        // Resequence
        foreach (ISequencedObject sequencedObject in targetCollection)
        {
            sequencedObject.SequenceNumber = sequenceNumber;
            sequenceNumber++;
        }

        // Set return value
        return targetCollection;
    }

    private void Initialise()
    {
        //Create inputList
        _doliInputCollection = new ObservableCollection<DoliInput>();

        //Add items
        _doliInputCollection.Add(new DoliInput("Load", 3, 2, 1));
        _doliInputCollection.Add(new DoliInput("Position", 3, 11, 1));
        _doliInputCollection.Add(new DoliInput("Position", 3, 2, 4));
        _doliInputCollection.Add(new DoliInput("Load", 3, 2, 1));

        //Subscribe to the event that gets trigger when change occurs
        _doliInputCollection.CollectionChanged += OnDoliCollectionChanged;

        //Start indexing items
        this.DoliInputCollection = SetCollectionSequence(this.DoliInputCollection);

        //Update if changes
        this.OnPropertyChanged("DoliInputCollection");
        this.OnPropertyChanged("GridParam");
    }
}
}

xaml文件

<Window x:Class="InteractiveGraph.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:InteractiveGraph"
    xmlns:dataGrid="clr-namespace:InteractiveGraph.Grid"
    xmlns:vc="clr-namespace:InteractiveGraph.BugFix"
    mc:Ignorable="d"
    Title="MainWindow" Height="502.869" Width="935.246" SizeChanged="Window_SizeChanged">
<Window.DataContext>
    <dataGrid:DataGridVM />
</Window.DataContext>
<Grid Background="LightGreen">
    <Grid.RowDefinitions>
        <RowDefinition Height="1*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid>
        <DataGrid   Grid.Row="0" Grid.Column="0" 
                    HorizontalAlignment="Center" Height="100" Margin="0" 
                    VerticalAlignment="Center" Width="522" 
                    ItemsSource="{Binding DoliInputCollection}" AllowDrop="True" SelectionMode="Extended"
                    SelectedItem="{Binding SelectedItem}"
                    AutoGenerateColumns="False" ColumnWidth="*"
                    Name="inputlist" 
                    CanUserSortColumns="False"
                    CanUserAddRows="True"
                    DataContextChanged="OnMainGridDataContextChanged" 
                    RowEditEnding="inputlist_RowEditEnding">

            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Ctrl type">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding CbItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                      SelectedValue="{Binding CTRL, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding Destination, Mode=TwoWay}" Header="Destination" />
                <DataGridTextColumn Binding="{Binding Speed, Mode=TwoWay}" Header="Speed" />
                <DataGridTextColumn Binding="{Binding Duration, Mode=TwoWay}" Header="Duration(s)" >
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Grid>
</Window>

背后的代码(我知道这应该是空的....)

 public partial class MainWindow : Window
{

    public List<string> CbItem { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        CbItem = new List<string> { "Position", "Load" };
    }

    //To be removed, trying to understand what is going wrong
    private void inputlist_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
    {
        Console.WriteLine("######COUNT " + _viewModel.DoliInputCollection.Count().ToString());
        foreach (var item in _viewModel.DoliInputCollection)
        {
            Console.WriteLine("CTRL = " + item.CTRL + ", destination = " + item.Destination.ToString() + ", SeqNum = " + item.SequenceNumber.ToString());
        }
    }
}

namespace InteractiveGraph.Utility
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    #region Protected Methods

    /// <summary>
    /// Fires the PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The name of the changed property.</param>
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            PropertyChanged(this, e);
        }
    }

    #endregion
}
}

ISequenceObject

namespace InteractiveGraph.Utility
{
    /// <summary>
    /// An object that can be given a sequential order in a collection.
    /// </summary>
    public interface ISequencedObject
    {
        /// <summary>
        /// The sequence number of the object
        /// </summary>
        int SequenceNumber { get; set; }

    }
}

ObservaleObject

namespace InteractiveGraph.Utility
{ 
    public class ObservableObject : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Protected Methods

        /// <summary>
        /// Raises the PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The name of the property that was changed.</param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                PropertyChanged(this, e);
            }
        }

        #endregion
    }
}

0 个答案:

没有答案