Я создал сетку данных, используя шаблон MVVM ( почти в точности этот пример ). Конечная цель состоит в том, чтобы иметь график, который отображает все данные из этой сетки данных, И эта сетка данных должна обновляться, когда точка графика перемещается вручную (перетаскивание). Построенные данные представляют собой набор входных данных для робота.
Я намеревался построить его с помощью 1 модели (список входных параметров), 2 моделей просмотра (одна для таблицы данных и одна для графика) и 2 представления (одно и то же окно).
Проблема: обе модели просмотра должны использовать / обновлять один и тот же ObservableCollection
, содержащий список входов.
Чтобы решить эту проблему, я попробовал несколько подходов:
- Шаблон посредника - я его не понимаю
- Внедрение зависимостей - То же, что и для шаблона посредника, все примеры Мне было сложно понять
- Singleton patter - кажется, я понимаю это, но не могу его правильно реализовать (я использую этот пример , который я считаю понятным)
Чтобы упростить задачу, в настоящее время я сосредоточен только на сетке данных. Итак, используя шаблон Singleton + MVVM, я пытаюсь заставить его работать так же, как и раньше (команды для добавления / удаления строки, перетаскивания, обновления ObservableCollection ).
Итак, это одноэлементный класс:
class SingletonDoliInputCollection : ViewModelBase
{
#region Events
void OnDoliCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Update item count
this.ItemCount = this.DoliInputCollection.Count;
// Resequence list
SetCollectionSequence(this.DoliInputCollection);
}
#endregion
#region Fields
private ObservableCollection<DoliInput> _doliInputCollection;
private int _itemCount;
//Singleton
private static SingletonDoliInputCollection _instance;
#endregion
#region Singleton Constructor
private SingletonDoliInputCollection() { }
#endregion
#region Properties
public ObservableCollection<DoliInput> DoliInputCollection
{
get => _doliInputCollection;
set
{
_doliInputCollection = value;
OnPropertyChanged("DoliInputCollection");
}
}
public static SingletonDoliInputCollection GetInstance(ObservableCollection<DoliInput> DoliInputCollection)
{
if (_instance == null)
{
_instance = new SingletonDoliInputCollection();
_instance.Initialise(DoliInputCollection);
}
return _instance;
}
public int ItemCount
{
get => _itemCount;
set
{
_itemCount = value;
OnPropertyChanged("ItemCount");
}
}
/// <summary>
/// Return selected item in the grid
/// </summary>
public DoliInput SelectedItem { get; set; }
#endregion
#region Manage Sequencing
/// <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;
}
#endregion
#region Private Methods
#region Initialise
private void Initialise(ObservableCollection<DoliInput> DoliInputCollection)
{
//Create inputList
_instance.DoliInputCollection = new ObservableCollection<DoliInput>();
//Add items
_instance.AddInput("Load", 3, 2, 1);
_instance.AddInput("Position", 3, 11, 1);
_instance.AddInput("Position", 3, 2, 4);
_instance.AddInput("Load", 3, 2, 1);
//Subscribe to the event that gets trigger when change occurs
_instance.DoliInputCollection.CollectionChanged += OnDoliCollectionChanged;
//Start indexing items
this.DoliInputCollection = SetCollectionSequence(this.DoliInputCollection);
//Update if changes
this.OnPropertyChanged("DoliInputCollection");
this.OnPropertyChanged("GridParam");
}
#endregion
#endregion
#region Public Methods
public void AddInput(string CTRL, double Destination, double Speed, double Duration)
{
this.DoliInputCollection.Add(new DoliInput(CTRL, Destination, Speed, Duration));
}
#endregion
}
Класс ViewModel выглядит так:
public class DataGridVM : ViewModelBase
{
#region Constructor
public ObservableCollection<DoliInput> DoliInputCollection { get; set; }
public DoliInput SelectedItem { get; set; }
public DataGridVM()
{
//ObservableCollection<DoliInput> DoliInputCollection = new ObservableCollection<DoliInput>();
SingletonDoliInputCollection doliInputs = GetDoliInputCollectionInstance(DoliInputCollection);
DoliInputCollection = doliInputs.DoliInputCollection;
SelectedItem = doliInputs.SelectedItem;
Console.WriteLine(doliInputs.DoliInputCollection.ToString());
}
#endregion
#region Properties
public ICommand DeleteItem { get; set; }
public ICommand AddRow { get; set; }
#endregion
#region Private Methods
#region Initialise
private static SingletonDoliInputCollection GetDoliInputCollectionInstance(ObservableCollection<DoliInput> DoliInputs)
{
SingletonDoliInputCollection singleton = SingletonDoliInputCollection.GetInstance(DoliInputs);
return singleton;
}
#endregion
#endregion
}
А для представления вот только пример форматирования столбца:
<!--[...]-->
xmlns:dataGrid="clr-namespace:InteractiveGraph.Grid"
<!--[...]-->
<DataGridTextColumn Binding="{Binding Path=(dataGrid:DoliInput.Speed), Mode=TwoWay}" Header="Speed" />
<!--[...]-->
Последняя упрощенная версия модели (есть еще 3 свойства: CTRL, назначение и продолжительность, здесь не отображаются)
public class DoliInput : ObservableObject, ISequencedObject
{
#region Fields
private double _speed;
private int _seqNb;
#endregion
#region Properties
public double Speed
{
get => _speed;
set
{
_speed = value;
OnPropertyChanged("Speed");
}
}
public int SequenceNumber
{
get => _seqNb;
set
{
_seqNb = value;
OnPropertyChanged("SequenceNumber");
}
}
#endregion
#region Constructor
public DoliInput(){ }
public DoliInput(string CTRL, double destination, double speed, double duration)
{
this._speed = speed;
}
#endregion
}
Я постарался сделать это как можно короче. Если нужна дополнительная информация, я могу ее добавить.
Disclamer : Очевидно, я не профессиональный программист. Я занимаюсь этим на стороне и стараюсь узнавать новое. Если вы думаете, что весь мой подход к этому коду неверен, я полностью открыт для нового.