|
This is a follow-up question to: [^] posted in the C# Q/A Forum.
Why not post this question in C# Q/A forum, as well ?
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
I have this sample data. Right now it is defined in a seperate C# file like this:
public class SampleData
{
public static ObservableCollection<Product> GetSampleData()
{
ObservableCollection<Product> teams = new ObservableCollection<Product>();
}
}
and I load the obsevableCollection inside GetSampleData().
It works and I am able to get the sample data anywhere in my program.
But how can I redesign this code so that I can create the sample data on the fly from outside the class?
|
|
|
|
|
0. 'as is' the code shown here will not work: your definition of 'GetSampleData' is supposed to return an ObservableCollection<product>, and it does not.
1. Why not make the Class 'static' as well ? As the code is now, the Class will have to be instantiated with 'new'
2. please explain more clearly exactly what you mean by "get the sample data on the fly from outside the class." You mean from a database ?
Would something like this work for you:
public static class SampleData
{
public static ObservableCollection<Product> teams = new ObservableCollection<Product>();
public static void GetSampleData()
{
// code here to access a database or whatever to fill the teams<Product> collection
}
}
In this type of access-model, once you have called 'GetSampleData,' and filled the 'teams' global static variable, you can access it from anywhere in your project by: SampleData.teams
Note: since you are using ObservableCollection, my guess is your intent is to make use of PropertyChanged and/or CollectionChanged facilties: I have not thought through the implications of making a static ObservableCollection.
There's a great new article here on CP about ObservableCollection I recommend you see: Enhanced ObservableCollection with ability to delay or disable notifications[^]
best, Bill
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
Dear friends I have simple experience programming with C#,but new to deal with graph data structure. when I got some examples from MSDN which is the following
I face this error message Error
'WindowsApplication4.Graph<t> does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()
'WindowsApplication4.Graph<l>GetEnumerator()' is either static, not public, or has the wrong return type.
and I had changed the return data type to all possible type and the error still the same please help me to overcome this problem.
#region Using directives
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
#endregion
namespace WindowsApplication4
{
public class Graph<T> : IEnumerable<T>
{
#region Private Member Variables
private NodeList<T> nodeSet;
#endregion
#region Constructors
public Graph() : this(null) { }
public Graph(NodeList<T> nodeSet)
{
if (nodeSet == null)
this.nodeSet = new NodeList<T>();
else
this.nodeSet = nodeSet;
}
#endregion
#region Methods
#region Add
#region AddNode
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
foreach (GraphNode<T> gnode in nodeSet)
yield return gnode.Value;
}
#endregion
public void AddNode(GraphNode<T> node)
{
nodeSet.Add(node);
}
public void AddNode(T value)
{
nodeSet.Add(new GraphNode<T>(value));
}
#endregion
#region Add*Edge Methods
public void AddDirectedEdge(T from, T to)
{
AddDirectedEdge(from, to, 0);
}
public void AddDirectedEdge(GraphNode<T> from, GraphNode<T> to)
{
AddDirectedEdge(from, to, 0);
}
public void AddDirectedEdge(GraphNode<T> from, GraphNode<T> to, int cost)
{
from.Neighbors.Add(to);
from.Costs.Add(cost);
}
public void AddDirectedEdge(T from, T to, int cost)
{
((GraphNode<T>)nodeSet.FindByValue(from)).Neighbors.Add(nodeSet.FindByValue(to));
((GraphNode<T>)nodeSet.FindByValue(from)).Costs.Add(cost);
}
public void AddUndirectedEdge(T from, T to)
{
AddUndirectedEdge(from, to, 0);
}
public void AddUndirectedEdge(GraphNode<T> from, GraphNode<T> to)
{
AddUndirectedEdge(from, to, 0);
}
public void AddUndirectedEdge(GraphNode<T> from, GraphNode<T> to, int cost)
{
from.Neighbors.Add(to);
from.Costs.Add(cost);
to.Neighbors.Add(from);
to.Costs.Add(cost);
}
public void AddUndirectedEdge(T from, T to, int cost)
{
((GraphNode<T>)nodeSet.FindByValue(from)).Neighbors.Add(nodeSet.FindByValue(to));
((GraphNode<T>)nodeSet.FindByValue(from)).Costs.Add(cost);
((GraphNode<T>)nodeSet.FindByValue(to)).Neighbors.Add(nodeSet.FindByValue(from));
((GraphNode<T>)nodeSet.FindByValue(to)).Costs.Add(cost);
}
#endregion
#endregion
#region Clear
public void Clear()
{
nodeSet.Clear();
}
#endregion
#region Contains
public bool Contains(T value)
{
return nodeSet.FindByValue(value) != null;
}
#endregion
#region Remove
public bool Remove(T value)
{
GraphNode<T> nodeToRemove = (GraphNode<T>)nodeSet.FindByValue(value);
if (nodeToRemove == null)
return false;
nodeSet.Remove(nodeToRemove);
foreach (GraphNode<T> gnode in nodeSet)
{
int index = gnode.Neighbors.IndexOf(nodeToRemove);
if (index != -1)
{
gnode.Neighbors.RemoveAt(index);
gnode.Costs.RemoveAt(index);
}
}
return true;
}
#endregion
#endregion
#region Public Properties
public NodeList<T> Nodes
{
get
{
return nodeSet;
}
}
public int Count
{
get { return nodeSet.Count; }
}
#endregion
}
}
|
|
|
|
|
Didn't look at everything, but IEnumerable<T>.GetEnumerator() is supposed to return a class of something that implements IEnumerator<T>. Its not supposed to return your object. IEnumerator<T> implements methods to do that.
|
|
|
|
|
From a quick scan of your code, it looks like you know that both IEnumerable<t> and IEnumerable() interfaces must both be implemented, but you have your non-generic 'GetEnumerator() commented out: why ?
The other thing that 'jumps out' from the code is that while 'Graph implements IEnumerable, you don't seem to be taking advantage that an instance of 'Graph is inherently a List.
To really help with this, I think we'd need to know how and where you implement 'GraphNode and 'NodeList.
Have you googled on this error message, and looked on StackOverFlow, as well as CP, for similar questions ?
best, Bill
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
The short answer to this is that IEnumerable<T> also mandates that you implement IEnumerable, which requires a method of signature
IEnumerator GetEnumerator()
Fortunately IEnumerator<T> similarly mandates IEnumerator, so you can fulfil this contract with an explicit interface implementation:
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
(If you need to write an enumerator yourself, there's a similar issue with the Current property in IEnumerator<T> and IEnumerator, and a similar fix to return the same value but cast to object.)
However, as already pointed out, your graph is essentially wrapping a NodeList, and that already implements IEnumerable<T>. Instead of making an intermediate iterator, why not just forward the interface methods directly to the inner list?
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return nodeList.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
(I've done both as explicit for symmetry and because you shouldn't be calling GetEnumerator directly; only one of them needs to be explicit.)
|
|
|
|
|
Dear Sir,
I had tried your kind suggestion ,but unfortunately faild as shown below.please could you help me by making the changes on the following code segment and returned it to me “I’m very sorry to bother you………”
Error 3 foreach statement cannot operate on variables of type 'WindowsApplication4.NodeList<t>' because 'WindowsApplication4.NodeList<t>' does not contain a public definition for 'GetEnumerator'
namespace WindowsApplication4
{
///
/// Represents a graph. A graph is an arbitrary collection of GraphNode
instances.
///
/// <typeparam name="T">The type of data stored in the graph's
nodes.
public class Graph<t> : IEnumerable<t>
{
#region Private Member Variables
private NodeList<t> nodeSet; // the set of nodes in the graph
#endregion
#region Constructors
public Graph() : this(null) { }
public Graph(NodeList<t> nodeSet)
{
if (nodeSet == null)
this.nodeSet = new NodeList<t>();
else
this.nodeSet = nodeSet;
}
#endregion
#region Methods
#region Add
#region AddNode
///
/// Adds a new GraphNode instance to the Graph
///
/// <param name="node" />The GraphNode instance to add.
///
#region IEnumerable<t> Members
///
/// Returns an enumerator that allows for iterating through the
contents of the graph.
public IEnumerator<t> GetEnumerator()
{
foreach (GraphNode<t> gnode in nodeSet)
yield return gnode.Value;
}
#endregion
////////////////////////////////////////////////////////////
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public void AddNode(GraphNode<t> node)
{
// adds a node to the graph
nodeSet.Add(node);
}
///
/// Adds a new value to the graph.
///
/// <param name="value" />The value to add to the graph
public void AddNode(T value)
{
nodeSet.Add(new GraphNode<t>(value));
}
#endregion
#region Add*Edge Methods
///
/// Adds a directed edge from a GraphNode with one value (from) to a GraphNode with another value (to).
///
/// <param name="from" />The value of the GraphNode from which the directed edge eminates.
/// <param name="to" />The value of the GraphNode to which the edge leads.
public void AddDirectedEdge(T from, T to)
{
AddDirectedEdge(from, to, 0);
}
and if I Changed it to public like this
public IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
Error 1 The modifier 'public' is not valid for this item
|
|
|
|
|
I assumed that NodeList inherited from List<T>. If it is a custom class, firstly, it probably shouldn't be (it is a list, it should be a List<Node<T>> unless there's a good reason for it not to be), and secondly, it must itself implement IEnumerable<T> as you are trying to foreach over it in the GetEnumerator method.
|
|
|
|
|
Dear BobJanova,
Agian sorry to bother you,
I would like to inform your highness I'm using
Visual Studio 2005 C# and Vista home Basic edition OS ,if they have some effects.
|
|
|
|
|
Hello experts,
even though I tried to create a minimal code sample, this question needs rather large code samples attached. Don't worry, all the interesting text is here, above all the code.
An application has to serialize data to a file and to de-serialize from that file. This works like a charm. The working example is attached in the first two code samples.
Now for the interesting part: the original working version is delivered to millions of satisfied customers. All their positive feedback encouraged the creation of version 2. Version 2 should of course be able to load data files from version 1. It is possible to change the data model without breaking compatibility, to some extend at least using ObsoleteAttribute and OptionalFieldAttribute . But when changes get more fundamental, other approaches are to be researched.
The third code sample shows an altered <cdoe>DataContainer class. In this example, it has to serialize one field that is not present in the original version. Therefore the well-known loading process fails.
To recover from the exception, another assembly is loaded. In my test case, it's the original assembly. It's delivered within the version 2 project resources.
The original assembly should load the legacy file. But it throws a TargetInvocationException instead. Its inner exception tells us that DataContainer has three members while there are only two de-serialized.
Now where does this legacy assembly know of DataContainer having three members nowadays?
It should have called its integrated version of DataContainer , which then had two members and therefore should load the legacy file without moaning.
However, here is the "minimal" working sample:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Test_Serialization_Versioning_Heavy
{
public partial class Form1 : Form
{
#region Declarations
string _filename = string.Empty;
DataContainer _dataContainer = new DataContainer();
#endregion
#region Init
public Form1()
{
_filename = System.IO.Path.Combine(Application.StartupPath, "datafile.xml");
InitializeComponent();
ShowData();
}
#endregion
#region User Interaction
private void btLoad_Click(object sender, EventArgs e)
{
_dataContainer = DataContainer.LoadDataContainter(_filename);
ShowData();
}
private void btSave_Click(object sender, EventArgs e)
{
_dataContainer.Save(_filename);
}
#endregion
private void ShowData()
{
pgData.SelectedObject = _dataContainer;
}
#region Vom Windows Form-Designer generierter Code
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
this.btLoad = new System.Windows.Forms.Button();
this.btSave = new System.Windows.Forms.Button();
this.pgData = new System.Windows.Forms.PropertyGrid();
this.tlpMain.SuspendLayout();
this.SuspendLayout();
this.tlpMain.ColumnCount = 3;
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 96F));
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 96F));
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.Controls.Add(this.btLoad, 0, 0);
this.tlpMain.Controls.Add(this.btSave, 1, 0);
this.tlpMain.Controls.Add(this.pgData, 0, 1);
this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpMain.Location = new System.Drawing.Point(0, 0);
this.tlpMain.Name = "tlpMain";
this.tlpMain.RowCount = 2;
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F));
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.Size = new System.Drawing.Size(386, 392);
this.tlpMain.TabIndex = 0;
this.btLoad.Anchor = System.Windows.Forms.AnchorStyles.None;
this.btLoad.Location = new System.Drawing.Point(10, 6);
this.btLoad.Name = "btLoad";
this.btLoad.Size = new System.Drawing.Size(75, 23);
this.btLoad.TabIndex = 0;
this.btLoad.Text = "Load";
this.btLoad.UseVisualStyleBackColor = true;
this.btLoad.Click += new System.EventHandler(this.btLoad_Click);
this.btSave.Anchor = System.Windows.Forms.AnchorStyles.None;
this.btSave.Location = new System.Drawing.Point(106, 6);
this.btSave.Name = "btSave";
this.btSave.Size = new System.Drawing.Size(75, 23);
this.btSave.TabIndex = 1;
this.btSave.Text = "Save";
this.btSave.UseVisualStyleBackColor = true;
this.btSave.Click += new System.EventHandler(this.btSave_Click);
this.tlpMain.SetColumnSpan(this.pgData, 3);
this.pgData.Dock = System.Windows.Forms.DockStyle.Fill;
this.pgData.Location = new System.Drawing.Point(3, 38);
this.pgData.Name = "pgData";
this.pgData.Size = new System.Drawing.Size(380, 351);
this.pgData.TabIndex = 2;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(386, 392);
this.Controls.Add(this.tlpMain);
this.Name = "Form1";
this.Text = "Form1";
this.tlpMain.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.TableLayoutPanel tlpMain;
private System.Windows.Forms.Button btLoad;
private System.Windows.Forms.Button btSave;
private System.Windows.Forms.PropertyGrid pgData;
#endregion
}
} The original DataContainer class
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
namespace Test_Serialization_Versioning_Heavy
{
[Serializable]
public class DataContainer
{
#region Declarations
private string _name = "NoName";
private int _someNumber = 3;
#endregion
#region Information Disclosure
public string Name
{
get { return (_name); }
set { _name = value; }
}
public int SomeNumber
{
get { return (_someNumber); }
set { _someNumber = value; }
}
#endregion
#region Actions
public void Save(string path)
{
using (
System.IO.Stream writeStream = new System.IO.FileStream(
path,
System.IO.FileMode.OpenOrCreate
)
)
{
IFormatter formatter = new Formatters.Soap.SoapFormatter();
formatter.Serialize(writeStream, this);
}
}
public static DataContainer LoadDataContainter(string path)
{
using (System.IO.Stream readStream = new System.IO.FileStream(path, System.IO.FileMode.Open))
{
IFormatter formatter = new Formatters.Soap.SoapFormatter();
return ((DataContainer)(formatter.Deserialize(readStream)));
}
}
#endregion
}
} After updating
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
namespace Test_Serialization_Versioning_Heavy
{
[Serializable]
public class DataContainer
{
#region Declarations
private string _name = "NoName";
private int _someNumber = 3;
private double _newDouble = 5.2;
#endregion
#region Information Disclosure
public string Name
{
get { return (_name); }
set { _name = value; }
}
public int SomeNumber
{
get { return (_someNumber); }
set { _someNumber = value; }
}
public double NewDouble
{
get { return (_newDouble); }
set { _newDouble = value; }
}
#endregion
#region Actions
public void Save(string path)
{
using (
System.IO.Stream writeStream = new System.IO.FileStream(
path,
System.IO.FileMode.OpenOrCreate
)
)
{
IFormatter formatter = new Formatters.Soap.SoapFormatter();
formatter.Serialize(writeStream, this);
}
}
public static DataContainer LoadDataContainter(string path)
{
try
{
using (
System.IO.Stream readStream = new System.IO.FileStream(
path,
System.IO.FileMode.Open
)
)
{
IFormatter formatter = new Formatters.Soap.SoapFormatter();
return ((DataContainer)(formatter.Deserialize(readStream)));
}
}
catch (Exception ex)
{
System.Reflection.Assembly legacyAssembly = System.Reflection.Assembly.Load(Properties.Resources.LegacyAssemblyV1_0_0_0);
Type[] legacyTypes = legacyAssembly.GetTypes();
Type legacyProjectType = legacyAssembly.GetType("Test_Serialization_Versioning_Heavy.DataContainer");
object legacyProjectObject = legacyProjectType.InvokeMember(
"LoadDataContainter",
System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.InvokeMethod,
null, null,
new object[] { path }
);
return (null);
}
}
#endregion
}
}
Ciao,
luker
|
|
|
|
|
|
Generally, that would be the good answer. As I already mentioned
"...at least using ObsoleteAttribute and OptionalFieldAttribute ..."
I am aware of the possibilities of Version Tolerant Serialization.
But in this case, I need something more powerful. Hence my approach to load a legacy assembly and make it load the legacy file.
Problem is, the legacy assembly throws an error on loading a file that it should be capable of loading. The error in turn refers to a data type that the legacy assembly cannot know of.
How can I make this work?
Ciao,
luker
|
|
|
|
|
You may need to load the assembly into a separate AppDomain – but that then makes it impossible to copy the object across once it's loaded in the other domain, so it doesn't really help. With my lobby client (which loads its game type modules at runtime and does some version control on them) I had big problems trying to get two version of the same class to operate within one AppDomain.
If the changes are more than just adding new fields, you might want to think about having the class unchanged and creating a new class which inherits from or wraps it. You might also want to look at the design: typically you should be serialising data, i.e. very simple data-containing objects, and I wouldn't expect them to change so much as to make the version tolerance in the framework insufficient.
(The kind of thing you're experiencing here is one reason why I don't like to use [Serializable] for long term persistence, i.e. saving to file or other permanent storage. I typically have read/write methods on the persistent classes which convert them to the string or bytes that are needed to recreate each object – often not the same thing as its complete internal state, which is what serialisation saves – and those methods can handle the reading of prior versions, particularly if you pass as a parameter the version which the file claims to be.)
|
|
|
|
|
hi all,
I am quite new on C# and want to prepare a GUI for an IP device which already has a web page. What I want to do is making my own menu with specific options. For example on web page there are 4 options that i can change/configure but in my GUI i just want to use 2 of them, i want to read these 2 options and want to reconfigure. Any help will welcome!
thx
|
|
|
|
|
i forgot to say that i am working on Microsoft Visual Studio 2010 C# and want to make a form application.
|
|
|
|
|
What's an IP device and what part of the GUI are you struggling with, creating a menu bar?
|
|
|
|
|
For example an IP relay. on its web page i can set the 4 relays on/off and i have config menu. in my gui i just want to play with 2 relays only. basicly it will be a button but how to connect this button click with relay?
|
|
|
|
|
Well the first thing to understand is the protocols used by the IP Relay to control it.
Then you would have to write a suitable communications class to do the interfacing, and on top of that the gui to do the user interaction.
Without more knowledge of the type/make/model of the IP Relay then nothing more can be added. In situations like this, Google and some of the Hardware sites can help. The OEMs usually have samples available on their websites.
|
|
|
|
|
Could you clarify:
1. you are asking for help only in how to make a GUI in a WinForms C# application using some form of menu ?
2. you have already solved all issues relating to how your C# application communicates with your IP device ? So the information you need to display in the C# application is available, and the means to take action ... sending whatever to the IP Device ... depending on the user's choices in the application ... is already worked out ?
3. By 'menu' do you mean the typical drop-down Menu Control ? ... or ... ?
best, Bill
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
That means that you have to analyze the source code of the html pages shown in your web browser.
Find out which actions are invoked on the web server of your device, when a button on the form is clicked (the protocol GET or POST, the address the browser sends the data to, the data which are sent), and then send the equivalent http requests from your application.
|
|
|
|
|
Ex:
If I send user the download url like http://www.mysite.com/downloads/file1.pdf
but there are file2.pdf,file3.pdf in the same folder and user can simple rename the file1.pdf to file2.pdf in the url and he can download file2.pdf.
How can we restrict users from doing this.
I really appreciate for you help....
Thanks
Nani
|
|
|
|
|
How about using randomly generated file names so that the user has no way of replacing the file name?
0100000101101110011001000111001011101001
|
|
|
|
|
You would have to keep the files in a different location and then use a Web Handler file (ASHX) to read the file bytes and Write them to the Response.
|
|
|
|
|
Nani - you actually need to invert your thinking on this. Should you be restricting the user from doing this? If the user has the permissions to download the file then why should you restrict it? If, however, you change the problem around to "should I allow a user to be able to download a file that they don't have permissions to?" then you get a totally different question, but a one that makes a lot of sense.
You can use the security aspects of ASP.NET - and combine this with ashx handlers to parse the request that's coming in - and control the users access to the files. BTW - this should have been asked in the ASP.NET forum, not this one.
|
|
|
|
|