I would like to send the character 'a' to the serial port.
I tried:
serialPort1.WriteLine("a");
but it's not actually sending the character 'a' to my board.
Any ideas?
I share to you a class created by me in a productive project. This Handles the serial connection and reading and writing buffer:
public class CommSERIAL : IComm
{
#region Events
public event EventHandler EvtOnConnect;
public event EventHandler EvtOnDisconnect;
public event EventHandler<OnDataReceivedEventArgs> EvtOnDataReceived;
#endregion
System.IO.Ports.SerialPort Rs232 = new System.IO.Ports.SerialPort();
private string m_Port;
public string Port
{
get { return m_Port; }
set { m_Port = value; }
}
private int m_Baud;
public int Baud
{
get { return m_Baud; }
set { m_Baud = value; }
}
private int m_DataBit;
public int DataBit
{
get { return m_DataBit; }
set { m_DataBit = value; }
}
private System.IO.Ports.StopBits m_stopBits;
public System.IO.Ports.StopBits StopBits
{
get { return m_stopBits; }
set { m_stopBits = value; }
}
private System.IO.Ports.Parity m_parity;
public System.IO.Ports.Parity Parity
{
get { return m_parity; }
set { m_parity = value; }
}
public void Connect()
{
if (!(Rs232.IsOpen))
{
Rs232.PortName = this.Port;
Rs232.BaudRate = this.Baud; ;
Rs232.DataBits = this.DataBit;
Rs232.StopBits = this.StopBits;
Rs232.Parity = this.Parity;
Rs232.ReadTimeout = 5000;
Rs232.Handshake = System.IO.Ports.Handshake.None;
Rs232.ReadTimeout = 1000;
Rs232.WriteTimeout = 500;
Rs232.Open();
}
}
public void Disconnect()
{
Rs232.Close();
if (EvtOnDisconnect != null)
EvtOnDisconnect(new object(), new System.EventArgs());
m_Connected = false;
}
public CommSERIAL()
{
this.ConnType = ConnType.Direct;
}
public bool Connected
{
get
{
return m_Connected;
}
}
private ConnType m_ConnType;
public ConnType ConnType
{
get { return m_ConnType; }
set { m_ConnType = value; }
}
public string ReadOnByte(int Lenght,char EndChar)
{
char[] bytes = new char[Lenght];
string ret = "";
int numBytesRead = 0;
while (bytes[numBytesRead] != EndChar && numBytesRead <= bytes.Length)
{
while (Rs232.Read(bytes, numBytesRead, 1) == 1 && bytes[numBytesRead] != EndChar && numBytesRead <= bytes.Length)
{
numBytesRead++;
}
}
foreach (char b in bytes)
ret += b.ToString();
return ret.Substring(0,numBytesRead);
}
public String ReadBuffer()
{
try
{
if (Rs232.IsOpen)
{
Byte[] readBuffer = new Byte[Rs232.ReadBufferSize + 1];
try
{
// If there are bytes available on the serial port,
// Read returns up to "count" bytes, but will not block (wait)
// for the remaining bytes. If there are no bytes available
// on the serial port, Read will block until at least one byte
// is available on the port, up until the ReadTimeout milliseconds
// have elapsed, at which time a TimeoutException will be thrown.
Int32 count = Rs232.Read(readBuffer, 0, Rs232.ReadBufferSize);
String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
return SerialIn;
}
catch (TimeoutException) { return ""; }
}
else
{
Thread.Sleep(50);
return "";
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public string Read()
{
return Rs232.ReadExisting();
}
public string ReadAll()
{
//TO DO
return "";
}
public void Write(string Data)
{
if (Rs232 == null)
throw new Exception("Must be connected before Write");
if (!Rs232.IsOpen)
throw new Exception("Must be opened before Write");
Rs232.Write(Data);
}
public void ClearBuffer()
{
Rs232.DiscardInBuffer();
}
private bool m_Connected;
#region IComm Members
private int m_Id;
public int Id
{
get
{
return m_Id;
}
set
{
m_Id = value;
}
}
#endregion
public override string ToString()
{
return this.ConnType.ToString();
}
#region IComm Members
#endregion
}
public interface IComm
{
ConnType ConnType
{
get;
set;
}
bool Connected
{
get;
}
int Id
{
get;
set;
}
void Connect();
void Disconnect();
void Write(string Data);
string Read();
string ReadOnByte(int Lenght, char EndChar);
String ReadBuffer();
void ClearBuffer();
string ReadAll();
event EventHandler EvtOnConnect;
event EventHandler EvtOnDisconnect;
event EventHandler<EventArgs.OnDataReceivedEventArgs> EvtOnDataReceived;
}
I hope that works for you
Are you using the serial port class?
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx
How do you know that it isn't sending the character? Is it possible that the baud/word length/parity setting are off and your board is just not recognizing the character?
Also, why c#? Just seems an odd choice for hardware IO.
Related
The button function, should take whatever text is in the combo box and place it within sleeper.traintype
private void Btn_Apply_Click(object sender, RoutedEventArgs e)
{
try
{
sleeper.trainType = CmbBox_TrainType.Text;
if (CmbBox_TrainType.Text == "Sleeper")
{
// instantiate the sleeper train
sleeper.trainType = CmbBox_TrainType.Text;
}
}
My sleeper train class (inheriting from overall train class)
public class Sleeper : Train
{
private string _intermediate, _intermediate1, _intermediate2, _intermediate3;
private bool _cabin;
public string intermediate
{
get
{
return _intermediate;
}
set
{
_intermediate = value;
}
}
public string intermediate1
{
get
{
return _intermediate1;
}
set
{
_intermediate1 = value;
}
}
public string intermediate2
{
get
{
return _intermediate2;
}
set
{
_intermediate2 = value;
}
}
public string intermediate3
{
get
{
return _intermediate3;
}
set
{
_intermediate3 = value;
}
}
The train class:
public class Train
{
private string _trainID, _departureDay, _departureStation, _destinationStation, _departureTime, _trainType;
private bool _firstClass;
public string timePunctuation = ":";
public string dayPunctuation = "/";
public string trainID
{
get
{
return _trainID;
}
set
{
// check if the vlaue has letters & numbers and that the length is correct
if(value.Length == 4 && Regex.IsMatch(value, "[A-Z][0-9]"))
{
_trainID = value;
}
else
{
throw new FormatException("That train ID is not valid! (Example: AA11)");
}
}
}
public string departureDay
{
get
{
return _departureDay;
}
set
{
if(value.Length == 0)
{
throw new FormatException("You need to choose a departure day!");
} else
{
_departureDay = value;
}
}
}
public string departureTime
{
get
{
return _departureTime;
}
set
{
if(value.Length != 5 || value.Contains(timePunctuation) == false)
{
throw new FormatException("The time must be in this format: (11:11 or 03:22)");
} else
{
_departureTime = value;
}
}
}
public string departureStation
{
get
{
return _departureStation;
}
set
{
if(value.Length == 0)
{
throw new FormatException("You must enter a departure station!");
} else
{
_departureStation = value;
}
}
}
public string destinationStation
{
get
{
return _destinationStation;
}
set
{
if(value.Length == 0)
{
throw new FormatException("You must enter a destination!");
} else
{
_departureStation = value;
}
}
}
public string trainType
{
get
{
return _trainType;
}
set
{
value = _trainType;
}
}
}
I'm using a combobox with three options "Sleeper", "Stopping" and "Express". When using breakpoints next to sleeper.trainType = CmbBox_TrainType.Text; it creates my class but states that my sleeper.trainType variable is null. But it says that
CmbBox_TrainType = "Sleeper"
Instantiate sleeper at the start with Sleeper sleeper = new Sleeper();
but have also tried to put it in the if and just before sleeper.trainType = CmbBox_TrainType.Text;
I want to remove Server1 from it's listbox, i'd want it to remove all the other items in the other listboxes associated with it as well. ("Server-Domain1" and all the "Server1-Domain1-CSR's"). Is there a way to do this?
To "bind" these list boxes i just used:
domainListBox.Items.Add((serverListBox.SelectedItem) + "-" + (this.domainTextbox.Text));
and
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-1"));
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-2"));
csrListBox.Items.Add((domainListBox.SelectedItem) + ("-CSR-3"));
If you choose your server from servers listbox, you can remove associated items like this (lets pretend there is some remove button, you selecting domain from listbox and clicking on remove button):
private void removeBtn_Click(object sender, EventArgs e)
{
List<string> items = csrListBox.Items.Cast<string>().ToList();
foreach (string item in csrListBox.Items)
{
Regex regex = new Regex(#"^" + domainListBox.SelectedItem + #"\w*");
Match match = regex.Match(item);
if (match.Success)
{
items.Remove(item);
}
}
csrListBox.DataSource = items;
}
Hope it helps.
Create a class that encapsulates the Server and it's details such as Domains and Csrs. Create a list of Servers and bind it to the first List Box. Then bind the other two List Boxes to the currently selected item of the first List Box. The end result may look like this:
serverListBox.ItemSource = Servers;
domainListBox.ItemSource = (serverListBox.SelectedItem as Server).Domains;
csrListBox.ItemSource = (serverListBox.SelectedItem as Server).Csrs;
This enables you to set the different List Boxes data without writing a lot of code that could make it unmaintainable.
Well, seeing your code, you just have to do something like this when you remove your server:
string server = serverListBox.SelectedItem as string;
serverListBox.Remove(server);
for (int i = domainListBox.Items.Count -1; i >-1; i--)
{
if (domainListBox.Items[i].ToString().StartsWith(server))
{
string domain = domainListBox.Items[i].ToString();
domainListBox.Items.RemoveAt(i);
for (int j = csrListBox.Items.Count-1; j > -1; j--)
{
if (csrListBox.Items[j].ToString().StartsWith(domain))
{
csrListBox.Items.RemoveAt(j);
}
}
}
}
Edit I have tested it now, this should work
a better option would be using observable pattern as
public class ObservableObject<T> : IList, IListSource
{
protected BindingSource src = null;
List<ListControl> Subscribers;
ObservableCollection<T> Data = new ObservableCollection<T>();
public bool IsReadOnly
{
get
{
return false;
}
}
public bool IsFixedSize
{
get
{
return false;
}
}
public int Count
{
get
{
return Data.Count;
}
}
public object SyncRoot
{
get
{
throw new NotImplementedException();
}
}
public bool IsSynchronized
{
get
{
throw new NotImplementedException();
}
}
public bool ContainsListCollection
{
get
{
return true;
}
}
object IList.this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = (T)value;
}
}
public T this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
public ObservableObject()
{
Data.CollectionChanged += Domains_CollectionChanged;
Subscribers = new List<ListControl>();
src = new BindingSource();
src.DataSource = Data;
}
private void Domains_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
src.ResetBindings(false);
}
public virtual void Subscribe(ListBox ctrl)
{
this.Subscribers.Add(ctrl);
//ctrl.DataBindings.Add(new Binding("SelectedValue", src, "Name",
// true, DataSourceUpdateMode.Never));
ctrl.DataSource = src;
}
public int Add(object value)
{
Data.Add((T)value);
return Data.Count - 1;
}
public bool Contains(object value)
{
return Data.Contains((T)value);
}
public void Clear()
{
Data.Clear();
}
public int IndexOf(object value)
{
return Data.IndexOf((T)value);
}
public void Insert(int index, object value)
{
Data.Insert(index, (T)value);
}
public void Remove(object value)
{
Data.Remove((T)value);
}
public void RemoveAt(int index)
{
Data.RemoveAt(index);
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public IEnumerator GetEnumerator()
{
return Data.GetEnumerator();
}
public IList GetList()
{
return Data;
}
}
public class BaseModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get { return _name; }
set
{
this._name = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
public class CSR : BaseModel
{
public override string ToString()
{
return Name;
}
}
public class Domain : BaseModel
{
public ObservableObject<CSR> CSRs { get; set; }
public Domain()
{
CSRs = new ObservableObject<CSR>();
}
public override string ToString()
{
return Name;
}
}
public class Server : BaseModel
{
public ObservableObject<Domain> Domains { get; set; }
public Server()
{
Domains = new ObservableObject<Domain>();
}
public override string ToString()
{
return Name;
}
}
public class DataModel : BaseModel
{
public ObservableObject<Server> Servers
{
get; set;
}
public DataModel()
{
Servers = new ObservableObject<Server>();
}
public override string ToString()
{
return Name;
}
}
on Form
DataModel m = new DataModel();
public Form1()
{
...
m.Servers.Subscribe(listBox1);
}
private void listBox2_Click(object sender, EventArgs e)
{
if (listBox2.SelectedIndex >= 0)
{
m.Servers[listBox1.SelectedIndex].Domains[listBox2.SelectedIndex].CSRs.Subscribe(listBox3);
}
}
private void listBox1_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex >= 0)
{
m.Servers[listBox1.SelectedIndex].Domains.Subscribe(listBox2);
}
}
you dont have to write code to remove items from forms in this perspective.removing object from model would do
I'm writing a language interpreter using C#. My user interface permits to visualize and change global variables and direct memory addresses in runtime.
I have problems when I try to visualize and change direct memory addresses as they can be visualized in different data sizes (BYTE, WORD and DWORD).
0 1 2 3
---------------------------------
| FFx16 | FFx16 | FFx16 | FFx16 | Memory
---------------------------------
- BYTE 3-
---- WORD 1 -----
------------ DWORD 0 ------------
So, If I'm visualizing BYTE3, WORD1 and DWORD0 in my UI, when I change value of BYTE3 my view doesn't upgrade WORD1 and DWORD0 values.
Memory and execution context (Model):
public class Memoria
{
private byte[] memoria;
public Memoria(int size)
{
memoria = new byte[size];
}
public void Write<T>(int index, Tipo t, T value)
{
int nBytes = t.GetBytes();
byte[] bytesArray = t.GetBytesArray(value);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytesArray);
for (int i = 0; i < nBytes; i++)
{
memoria[index+ i] = bytesArray[i];
}
}
}
public class Context
{
public Memoria DataMem { get; set; }
public Dictionary<int, IVariableObservable> VarGlobal { get; private set; }
public Dictionary<int, IVariableObservable> DirectAdress { get; private set; }
public InsertValues ()
{
foreach (IVariableObservable v in VarGlobal.Values)
{
Action action = () => v.Valor = v.InitValue;
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, action);
v.InsertValue();
}
}
public UpdateValue (int index)
{
IVariableObservable v = VarGlobal[index];
v.UpdateValue();
}
}
}
// * Language interpreter types are represented in Tipo objects
public abstract class Tipo
{
//* ....... More methods
public virtual int GetBytes()
{
return 0;
}
// * UI Representation
public virtual T GetUIRepresentation<T>(object valor)
{
return (T)Convert.ChangeType(valor, typeof(T));
}
}
Variable (Model):
public interface IVariableObservable : INotifyPropertyChanged
{
string Name { get; }
Tipo Tipo { get; }
object Valor { get; set; }
object InitValue { get; set; }
int Offset { get; set; }
Memoria DataMem { get; set; }
void InsertValue()
void UpdateValue();
void OnPropertyChanged(string propertyName);
}
public interface IVariableObservable<T> : IVariableObservable
{
new T Valor { get; set; }
new T InitValue { get; set; }
}
public class VariableObservable<T> : INotifyPropertyChanged, IVariableObservable<T>
{
private T valor;
public T Valor
{
get
{
return this.valor;
}
set
{
if (value.ToString() == this.valor.ToString())
return;
this.valor = value;
this.OnPropertyChanged("Valor");
}
}
object IVariableObservable.Valor
{
get { return Valor; }
set
{
Valor = Tipo.GetUIRepresentation<T>(value);
}
}
public Memoria DataMem { get; set; }
public void InsertValue()
{
DataMem.Write<T>(Offset, Tipo, Valor);
}
public void UpdateValue()
{
Valor = DataMem.Read<T>(Offset, Tipo);
}
}
My viewmodel:
public class VariableViewModel : WorkspaceViewModel
{
readonly IVariableObservable _variable;
readonly ObserverRepository _observerRepository;
public VariableViewModel(IVariableObservable variable, ObserverRepository observerRespository)
{
if (variable == null)
throw new ArgumentNullException("variable");
if (observerRespository == null)
throw new ArgumentNullException("observerRespository");
_variable = variable;
_observerRepository = observerRespository;
this._variable.PropertyChanged += this.OnVariableValueChanged;
}
private void OnVariableValueChanged(object sender, EventArgs e)
{
this.OnPropertyChanged("Valor");
}
public object Valor
{
get
{
return _variable.Valor;
}
set
{
if (value == _variable.Valor)
return;
_variable.Valor = value;
this.OnPropertyChanged("Valor");
_variable.InsertValue();
}
}
}
Is there any way to check changes in the different memory positions and propagate changes to all memory addresses which share those memory positions?
OK so as discussed in comments I didn't fix your code so much as re-write it entirely to use a different architecture that I think will work better for you assuming it doesn't break other functionality you require.
The main goal of my code was to make it so variables didn't keep copies of their values but instead looked to the memory store itself when retrieving the value and likewise using the memory store to set its value.
All variables store is a 'pointer' to a memory location (an address within a IMemory object). The IMemory object provides Read and Write operations to read and write one or more contiguous bytes from/to the memory.
IMemory exposes a MemoryChanged event which fires whenever a Write operation occurs. Variables attached themselves to this event in their constructor and upon receiving the event they check whether any of the changed addresses cover any part of the variable. If they do then the variable fires its INotifyPropertyChanged event which can be use by WPF et al to monitor for variable updates.
And now the code:
public interface IMemory
{
void Write(int address, params byte[] bytes);
byte[] Read(int address, int numBytes);
byte Read(int address);
event MemoryChangedEventHandler MemoryChanged;
}
public class Memory : IMemory
{
private readonly byte[] _memory;
public Memory(int size)
{
_memory = new byte[size];
}
public void Write(int address, params byte[] bytes)
{
for (int offset = 0; offset < bytes.Length; offset++)
{
_memory[address + offset] = bytes[offset];
}
UpdateMemory(address, bytes.Length);
}
public byte[] Read(int address, int numBytes)
{
return _memory.Skip(address).Take(numBytes).ToArray();
}
public byte Read(int address)
{
return _memory[address];
}
private void UpdateMemory(int address, int length)
{
if (MemoryChanged != null)
{
MemoryChanged(this, new MemoryChangedEventArgs
{
StartAddress = address,
EndAddress = address + length
});
}
}
public event MemoryChangedEventHandler MemoryChanged;
}
public delegate void MemoryChangedEventHandler(object sender, MemoryChangedEventArgs e);
public class MemoryChangedEventArgs
{
public int StartAddress { get; set; }
public int EndAddress { get; set; }
}
public class IntVariable : INotifyPropertyChanged
{
private readonly int _address;
private readonly Memory _memory;
public IntVariable(int address, Memory memory)
{
_address = address;
_memory = memory;
_memory.MemoryChanged += MemoryChanged;
}
private void MemoryChanged(object sender, MemoryChangedEventArgs e)
{
int startAddress = _address;
int endAddress = startAddress + sizeof (int);
int changedStartAddress = e.StartAddress;
int changedEndAddress = e.EndAddress;
if (IsVariableChanged(startAddress, changedStartAddress, endAddress, changedEndAddress))
{
OnPropertyChanged("Value");
}
}
private static bool IsVariableChanged(int startAddress, int changedStartAddress, int endAddress, int changedEndAddress)
{
return Math.Max(startAddress, changedStartAddress) <= Math.Min(endAddress, changedEndAddress);
}
public int Value
{
get
{
var intBytes = _memory.Read(_address, sizeof(int));
return BitConverter.ToInt32(intBytes, 0);
}
set
{
var intBytes = BitConverter.GetBytes(value);
_memory.Write(_address, intBytes);
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
So you would construct your Memory object then create IntVariable (obviously you would create different variable types as required for your different visualisations) objects that reference the Memory object and an address within the memory.
E.g.
var _memory = new Memory(20);
var variable1 = new IntVariable(0, _memory);
var variable2 = new IntVariable(0, _memory);
Then doing variable1.Value = 4; would make variable1 and variable2 fire their INotifyPropertyChanged event.
Hope this is what you were looking for.
Inner Collection
public class ItemsDetails
{
//Constructor
public ItemsDetails(int iID,
string sItemName,
Decimal iPrice,
int iQuantity,
int iPostalCode,
bool bisDB,
string SImagePath)
{
this.iID = iID;
this.sItemName = sItemName;
this.iPrice = iPrice;
this.iquantity = iQuantity;
this.iPostalCode = iPostalCode;
this.bisDB = bisDB;
this.sImagePath = SImagePath;
}
public ItemsDetails()
{
}
#region PrivateProperties
private int iID;
private string sItemName;
private Decimal iPrice;
private int iquantity;
private int iPostalCode;
private string sImagePath;
private int iMasterID;
#endregion
//static List<ItemsDetails> itemsDetails = new List<ItemsDetails>();
#region public Properties
public bool bisChanged = false;
public bool bisDB = true;
#endregion
public int IMasterID
{
get
{
return this.iMasterID;
}
set
{
if (this.iMasterID != value)
bisChanged = true;
this.iMasterID = value;
}
}
public bool BisChanged
{
get
{
return this.bisChanged;
}
set
{
this.bisChanged = value;
}
}
public int IPostalCode
{
get
{
return this.iPostalCode;
}
set
{
if (this.iPostalCode != value)
bisChanged = true;
this.iPostalCode = value;
}
}
public int Iquantity
{
get
{
return this.iquantity;
}
set
{
if (this.iquantity != value)
bisChanged = true;
this.iquantity = value;
}
}
public Decimal IPrice
{
get
{
return this.iPrice;
}
set
{
if (this.iPrice != value)
bisChanged = true;
this.iPrice = value;
}
}
public string SItemName
{
get
{
return this.sItemName;
}
set
{
if (this.sItemName != value)
bisChanged = true;
this.sItemName = value;
}
}
public string SImagePath
{
get
{
return this.sImagePath;
}
set
{
if (this.sImagePath != value)
bisChanged = true;
this.sImagePath = value;
}
}
public int IID // unique id
{
get
{
return this.iID;
}
set
{
if (this.iID != value)
bisChanged = true;
this.iID = value;
}
}
}
Main collection
public class ItemsMapping
{
private int itemMasterID;
private string sCatagoryName;
private string sImagePath;
private ICollection<ItemsDetails> iCollectionItemDetails;
public string SImagePath
{
get
{
return this.sImagePath;
}
set
{
this.sImagePath = value;
}
}
public string SCatagoryName
{
get
{
return this.sCatagoryName;
}
set
{
this.sCatagoryName = value;
}
}
public ICollection<ItemsDetails> ICollectionItemDetails
{
get
{
return this.iCollectionItemDetails;
}
set
{
this.iCollectionItemDetails = value;
}
}
public int ItemMasterID
{
get
{
return this.itemMasterID;
}
set
{
this.itemMasterID = value;
}
}
}
Object of collection
Collection<ItemsMapping> objItemCollection = getdata();// from db
Collection<ItemsDetails> objDeleteItems = itemsToDelete();// from selected items
Result i need to delete items from inner collection objItemCollection based on objDeleteItems collection.
I expect without using foreach/for loop. Trying to find solution on linq
Thanks in advance..
Linq (Language-Integrated Query)is for querying, not for modifying (i.e. updating, adding, deleting). Use foreach loop if you want to modify collection.
You can write query which returns set of items without those you want to delete, and then use results of this query instead of your original collection. If you have same instances of ItemsDetails objects in both collections (otherwise you will need to override Equals and GetHashCode of ItemsDetails class), and you don't need duplicates in result:
objItemCollection.ICollectionItemDetails =
objItemCollection.ICollectionItemDetails.Except(objDeleteItems);
But I would go without query. Simple loop will do the job (overriding of Equals and GetHashCode still required if you don't use same instances of ItemsDetails):
foreach(var item in objDeleteItems)
objItemCollection.ICollectionItemDetails.Remove(item);
You can move this logic to extension method
public static void RemoveAll<T>(
this ICollection<T> source, IEnumerable<T> itemsToRemove)
{
if (source == null)
throw new ArgumentNullException("source");
foreach(var item in itemsToRemove)
source.Remove(item);
}
Now code will look like:
objItemCollection.ICollectionItemDetails.RemoveAll(objDeleteItems);
I need help with this code
#region Events
public class DownloadProgressChangedEventArg
{
private long _ProgressPercentage;
private long _BytesReceived;
private long _TotalBytesToReceive;
public DownloadProgressChangedEventArg(long BytesReceived, long TotalBytesToReceive)
{
_BytesReceived = BytesReceived;
_TotalBytesToReceive = TotalBytesToReceive;
_ProgressPercentage = BytesReceived * 100 / (TotalBytesToReceive);
}
public long BytesReceived { get { return _BytesReceived; } set { _BytesReceived = value; } }
public long ProgressPercentage { get { return _ProgressPercentage; } set { _ProgressPercentage = value; } }
public long TotalBytesToReceive { get { return _TotalBytesToReceive; } set { _TotalBytesToReceive = value; } }
}
public delegate void DownloadProgressChangedEventHandler(Api.GetSong.GetObject.Object Sender, DownloadProgressChangedEventArg e);
public event DownloadProgressChangedEventHandler DownloadProgressChangedEvent;
public class DownloadCompletedEventArg
{
private bool _Cancelled;
private Exception _Error;
public DownloadCompletedEventArg(Exception Error, bool Cancelled)
{
_Cancelled = Cancelled;
_Error = Error;
}
public bool Cancelled { get { return _Cancelled; } set { _Cancelled = value; } }
public Exception Error { get { return _Error; } set { _Error = value; } }
}
public delegate void DownloadCompletedEventHandler(Api.GetSong.GetObject.Object Sender, DownloadCompletedEventArg e);
public event DownloadCompletedEventHandler DownloadCompletedEvent;
#endregion
WebClient wb;
public void DownloadFileAsync(Api.GetSong.GetObject.Object Object, String FileLocation)
{
String DownloadLink = GetStreamUri(Object);
String FileTitle = Object.Title + "." + Object.Type;
String FileLocations = Path.Combine(FileLocation,FileTitle);
if (!DownloadLink.StartsWith("rtmp"))
{
if (wb == null)
{
wb = new WebClient();
wb.DownloadFileCompleted += delegate(object sender, AsyncCompletedEventArgs e) { DownloadCompletedEvent(Object, new DownloadCompletedEventArg(e.Error, e.Cancelled)); };
wb.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e) { DownloadProgressChangedEvent(Object, new DownloadProgressChangedEventArg(e.BytesReceived, e.TotalBytesToReceive)); };
}
wb.DownloadFileAsync(new Uri(DownloadLink), FileLocations);
//throw:
//WebClient does not support concurrent I/O operations.
}
else
{
//Düzenlencek
}
}
public void DownloadFileCancel()
{
if (wb.IsBusy && wb != null)
{
wb.CancelAsync();
}
}
When calling DownloadFileAsync method you have to make sure it completes before trying to download again.
This answer will help you.