|
Well Bill,
I tried your code, I just don't think I'm including it right in my code.
I managed to get the node text listed in columns and their values
listed below each node.
Now I need to figure out how to edit the value in list view and then save them, also apply an image list to the tree view with
different images for nodes.
Here is what I have:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace TestXml
{
public partial class test : Form
{
public test()
{
InitializeComponent();
}
private string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
XmlDocument xDoc = new XmlDocument();
List<string> values = new List<string>();
private void test_Load(object sender, EventArgs e)
{
textBox1.Text = path + @"\Graw Mission Script\mission.xml";
}
private void button1_Click(object sender, EventArgs e)
{
xDoc.Load(textBox1.Text);
StreamReader sr = new StreamReader(path + @"\Graw Mission Script\mission.xml");
textBox2.Text = sr.ReadToEnd();
try
{
treeView1.Nodes.Clear();
treeView1.Nodes.Add(xDoc.DocumentElement.Name);
AddNode(xDoc.DocumentElement, treeView1.Nodes[0]);
treeView1.CollapseAll();
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
public void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
XmlAttributeCollection atts = inXmlNode.Attributes;
TreeNode tNode = new TreeNode("Attributes");
if (atts.Count != 0)
{
foreach (XmlAttribute att in atts)
{
tNode.Nodes.Add(att.Name).Nodes.Add(att.Value);
}
inTreeNode.Nodes.Add(tNode);
}
foreach (XmlNode xNode in inXmlNode.ChildNodes)
{
switch (xNode.NodeType)
{
case XmlNodeType.Element:
tNode = new TreeNode("<" + xNode.Name + ">");
AddNode(xNode, tNode);
break;
case XmlNodeType.Comment:
tNode = new TreeNode("<!--" + xNode.Value + "-->");
break;
case XmlNodeType.CDATA:
tNode = new TreeNode("#cdata " + xNode.Value);
break;
default:
throw new Exception("Unexpected NodeType: " + xNode.NodeType.ToString());
}
inTreeNode.Nodes.Add(tNode);
}
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
listView1.Clear();
TreeView tv = (TreeView)sender;
if (tv.SelectedNode.Text != "Attributes")
{
return;
}
if (tv.SelectedNode.Parent == null || tv.SelectedNode.GetNodeCount(false) == 0) return;
{
foreach (TreeNode tvNode in tv.SelectedNode.Nodes)
{
listView1.Columns.Add(tvNode.Text);
values.Add(tvNode.Nodes[0].Text);
}
ListViewItem item = listView1.Items.Add(values[0]);
values.RemoveAt(0);
if (values.Count > 0)
{
item.SubItems.AddRange(values.ToArray());
}
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
any help with that would be greatly appreciated.
modified 9-Mar-14 18:16pm.
|
|
|
|
|
I will take a look at your current code later today (GMT + 07 here). cheers, Bill
“The best hope is that one of these days the Ground will get disgusted enough just to walk away ~ leaving people with nothing more to stand ON than what they have so bloody well stood FOR up to now.” Kenneth Patchen, Poet
|
|
|
|
|
I really appreciate it cheers
|
|
|
|
|
If you go with the "symmetric dictionary" strategy I suggested, then synchronized updating of edits of the Labels of TreeView Nodes, or ListView Items is easy:
private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
currentNode = e.Node;
if (dctTNodeToLvItm.TryGetValue(currentNode, out currentLVItem))
{
currentLVItem.Text = e.Label;
}
}
private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
currentLVItem = listView1.Items[e.Item];
if (dctLvItmToTNode.TryGetValue(currentLVItem, out currentNode))
{
currentNode.Text = e.Label;
}
} More later today, as I have time.
“The best hope is that one of these days the Ground will get disgusted enough just to walk away ~ leaving people with nothing more to stand ON than what they have so bloody well stood FOR up to now.” Kenneth Patchen, Poet
|
|
|
|
|
I'm not really clear on exactly what your intended structure for the TreeView and ListView contents, and interaction are; the reason you create ListView Columns from some TreeNodes escapes me.
And, it is clear that I'd have to really know the details of your data, and the Application structure, to really give you useful feedback. However, I don't have time to really "get my head" into the deep structure of your Application.
I think the most helpful thing I can do is to send you a zipped .NET 4.0 sample (source code) Application that demonstrates TreeView and ListView synchronization via "symmetric" Dictionaries, demonstrates Node and ListViewItem synchronized text/label editing, etc. : [^]. The file has had the executables ripped out to make it smaller: you will need to re-compile. Let me know if you have any problem opening/using the sample Application.
It's always helped me to have working code to study, and then to learn by altering the code.
Hope it's helpful !
I will continue to monitor this thread to see if more specific questions come up.
“The best hope is that one of these days the Ground will get disgusted enough just to walk away ~ leaving people with nothing more to stand ON than what they have so bloody well stood FOR up to now.” Kenneth Patchen, Poet
|
|
|
|
|
Bill,
I just don't know how to apply the code to my code
I tried, so I must be doing something wrong.
and Obviously no one here knows how to do it.
cause if they did I would have an answer.
|
|
|
|
|
<pre lang="xml">I have Two Subscribers 1.SubA 2.SubB I have a table. Table name : Names
I have City column(nvarchar) in my Names table and it is unique key.
User 'A' connects to SubA. user 'B' connects to SubB.
A inserts a row with 'ABC' in to Names table @ 10:30 am.
It will take 20 min to update the publisher. 'B' inserts a row with 'ABC' in to Names table @10:35 am.
I have the unique constraint on the table so.User A's input is updated in the publisher @10:50.
But user B's input caught in the conflicts.
I want the city column should be unique across all the subs.
How could i handle this?How should i display proper message for user B?How should i do validation across all the subscribers</pre></pre>
|
|
|
|
|
I would create a table that stores locks and then lock each row as a user accesses it, so if User A creates a row and is still using that you leave the lock on until User A commits that record. When User B tries to access a row or create a row you check if that row is locked before allowing User B to do anything.
|
|
|
|
|
Probably the safest way to do this is to:
A: catch the exception thrown by the database and bubble it up to the user (in a friendly way)
or
B: add a where clause to your insert (insert into ... where cityname <> '[cityname]' ). Retrieve the updated number of rows of your insert query. If it is 0, tell the user the insert was not successfull.
Putting a lock on things poses many new problems.
hope this helps.
|
|
|
|
|
Wow that is really ugly, you have 2 subscriber databases where users enter data and it takes 20 minutes for that information to propagate to the publisher and you want the unique constraint validation on publisher.
I know nothing about distributed database design but this seems completely wrong. I would think the data entry should target the publisher and the subscriber should then take the results.
How do you proposed to get over the 20 minute time lag, forward quantum computing has not been invented yet.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
@MycroftHolmes,I am new to this distributed database design.When they told me this I was shocked as well.Can anybody please suggest any documents on winform applications with replicated data base.
thanks
|
|
|
|
|
private void AddProducts()
{
int i = 1;
foreach (TabPage tp in tabControl1.TabPages)
{
ObjectQuery<tblProducts> filteredProduct=new ObjectQuery<tblProducts>("Select value p from tblProducts as p where p.ProductType="+i,afos);
FlowLayoutPanel flp = new FlowLayoutPanel();
flp.Dock = DockStyle.Fill;
foreach(tblProducts tprod in filteredProduct)
{
Button b = new Button();
b.Size = new Size(100, 100);
b.Image = tprod.ProductImage;
b.Text=tprod.ProductName;
b.Tag = tprod;
b.Click += new EventHandler(UpdateProductList);
flp.Controls.Add(b);
}
tp.Controls.Add(flp);
i++;
}
}
Please help. I want to automatically call an image from the database and make it an image in the button..I have managed to have the Button automatically add depending on the number of Products on the database, there's no solid button. My only problem is to have the button's image set automatically from the images in the database.
Thank you so much.
|
|
|
|
|
And what is the result of the code that you show?
It's not clear what problem you are having.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
|
I am using the following code to convert from one type of object to another. It works fine, but I am looking for a way to improve performance:
public static object ConvertObject(object source, Type targetType)
{
object result;
Type sourceType = source.GetType();
DataContractSerializer sourceSerializer = new DataContractSerializer(sourceType);
using (MemoryStream ms = new MemoryStream())
{
DateTime start = DateTime.Now;
sourceSerializer.WriteObject(ms, source);
TimeSpan writeObjectTime = DateTime.Now - start;
ms.Seek(0, SeekOrigin.Begin);
DataContractSerializer targetSerializer = new DataContractSerializer(targetType);
XmlReader r = XmlReader.Create(ms);
DynamicObjectSerializer.MyReader myreader = new DynamicObjectSerializer.MyReader(r);
start = DateTime.Now;
result = targetSerializer.ReadObject(myreader);
TimeSpan readObjectTime = DateTime.Now - start;
LoggerHolder.LogDebug("\"{0}\" Write Time = {1}, Read Time = {2}", source.GetType().Name, writeObjectTime, readObjectTime);
}
return result;
}
Using the MemoryStream actually slows the process down since the object is first being written to it and then read from it. If it was possible to serialize the source object to the target one directly it would have been taken half the time. Any idea how this can be done?
Thanks.
|
|
|
|
|
I think it may be valuable for you if you give more detail on what type of object conversion you are performing here.
Measuring elapsed time using DateTime is well-known to be "limited" in accuracy. Starting with .NET 2.0, you can use the 'StopWatch in the System.Diagnostics library timer to get more accurate results: [^].
Executing the code several times before starting a timing operation is also believed to improve timing accuracy by eliminating any possible one-time costs of getting the code "jitted."
There are several articles here on CodeProject dealing with accurate timing: just search.
“The best hope is that one of these days the Ground will get disgusted enough just to walk away ~ leaving people with nothing more to stand ON than what they have so bloody well stood FOR up to now.” Kenneth Patchen, Poet
|
|
|
|
|
I know how to measure time - thanks - this is not the issue here.
I'm looking for someone with DataContractSerializer and serialization experience.
Thanks.
|
|
|
|
|
There was no need to get short with Bill. He was only trying to give you a bit of good advice. Using a DateTime to measure code timing, clearly shows you do not know how to measure time.
Everyone dies - but not everyone lives
|
|
|
|
|
Sorry - didn't mean to insult in no way - However, measuring is not the issue here - i am quite sure with the results since the times of the operations are long (~10 seconds) because the objects contains a lot of data - it is not milliseconds of difference.
|
|
|
|
|
You should consider using Fasterflect[^] or Automapper[^]. Your current implementation is hugely malperformant.
[Edit]
And you're really mapping between objects, not converting types, right?
[/Edit]
/ravi
|
|
|
|
|
Object converting - right.
The problem is that i want to convert objects without knowing its members - it should be done using their names (one property data in object one is copied to object two's property which has the same name).
using serialization i can serialize one object from one module to an object of another module easily.
I was looking for a way to serialize from one object to another without using a memory stream in the middle - that will solve my problem.
|
|
|
|
|
impeham wrote: it should be done using their names That's exactly what I thought you wanted to do.
You're mapping (not converting) objects. Use Automapper instead of serialization. It's orders of magnitude faster.
/ravi
|
|
|
|
|
i will look into it - thanks a lot
|
|
|
|
|
After checking AutoMapper i realized that i need to specifically map all internal types of the objects from source to target. this requires as my objects can contain many types and it will require a LOT of work (not to mention maintenance as they change) before it can be used and i need something to do the conversions automatically with minimal work => leads me to my first posted code.
So i return to the original question - is it possible to skip the MemoryStream read/write?
|
|
|
|
|
impeham wrote: is it possible to skip the MemoryStream read/write? Only if you write mappings for each internal object.
My philosophy is to build Clone() methods for each object (class), and call them for nested objects as required. Implementing Clone() is easily done by calling .NET's MemberwiseClone() for most properties. You will find the effort required to do this small in comparison to the run-time performance gain.
/ravi
|
|
|
|