|
You can't. Instead, split your array and pass each value as part of the WHERE clause:
private DataRow[] SelectRows(string field, string[] values)
{
if (field == null || values == null)
throw new ArgumentNullException(field == null ? "field" : "values");
if (values.Length < 1) throw new ArgumentException();
StringBuilder sb = new StringBuilder();
for (int i=0; i<values.Length; i++)
{
sb.AppendFormat("{0} = {1}", field, value);
if (i < (values.Length - 1))
sb.Append(" AND ");
return dataTable1.Select(sb.ToString());
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am creating a windows app in C# with a ListView control. It has three columns which are being filled with a ListViewItem (One .Text and two .SubItems being added to generate)
My problem is I can not figure out how to grab the text entered in one of the columns when someone clicks on one of the items. FullRowSelect is set to True and I'd like to keep it that way if possible. The first row is a list of FileNames, second the size and the third a mod date. On click, I want to simply open the file that was selected.
I've also noticed, while trying the SelectedItems/SelectedIndices options that they tend to be called twice on change. The first is a null value (for an Int??) and the second is the correct option.
Any help would be appreciated, I'm still going through articles on the Web regarding this control, but everything is oriented on sorting - not how to execute some code based on the selection. Thanks!
|
|
|
|
|
Get the index of the ListViewItem and get the sub item:
private void listView1_SelectedIndexChanged(object sender,
EventArgs e)
{
int index = listView1.SelectedIndex;
if (index >= 0)
{
ListViewItem item = listView1.Items[index];
string value = item.SubItems[1];
MessageBox.Show(value);
}
} If you actually want the column that the user clicked on, you need to perform a hit text:
private int GetColumnIndex()
{
Point p = listView1.PointToClient(
new Point(MousePosition.X, MousePosition.Y));
int width = 0;
foreach (ColumnHeader header in listView1.Columns)
{
width += header.Width;
if (p.X < width) return header.Index;
}
return -1;
} You could call this method to get the column index (be mindful that it could be -1) and use that as the index into ListViewItem.SubItems .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I had to modify it a bit:
int index = listView1.FocusedItem.Index;
if (index >= 0)
{
ListViewItem item = listView1.Items[index];
string value = item.SubItems[0].Text;
MessageBox.Show(value);
}
(There is no listView1.SelectedIndex)
Unfortunately I still have the same problem, the method fires twice. Once if its the first time I selected something, but on subsequent selections - it will show what the currently selected item is and then the new one. Any ideas why?
|
|
|
|
|
Adam Hable wrote:
(There is no listView1.SelectedIndex)
Oops. Sorry about that. I sometimes seem to miss something like that when throwing out examples.
Be sure that in your event handler (which I assume is the method you're talking about) that you don't set the selected index mistakenly using an assignment operator (=) instead of an equals operator (==). It could even by by mistake.
I do work a lot with ListView controls and have even done a lot to extend them with functionality (overriding WndProc ) provided by the List-View common control which ListView enscapsulates. I've never had the problem you're having.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Obviously not a problem, I just wanted to make sure I didn't make a mistake by trying something else. Here is the entire event:
private void listView1_SelectedIndexChanged(object sender, System.EventArgs e)
{
int index = listView1.FocusedItem.Index;
if (index >= 0)
{
ListViewItem item = listView1.Items[index];
string value = item.SubItems[0].Text;
MessageBox.Show(value);
}
}
I created a new project and left defaults (So that's why the 'listView1' naming) -- but it fires twice on the MessageBox.Show I agree - it shouldn't, so that's why I'm so confused!
I did just uninstall VS.Net 2k2 Pro and install a fresh copy of VS.Net 2k3 Ent. Architect, I doubt that has anything to do with this error but...could it?
|
|
|
|
|
Adam Hable wrote:
I did just uninstall VS.Net 2k2 Pro and install a fresh copy of VS.Net 2k3 Ent. Architect, I doubt that has anything to do with this error but...could it?
VS.NET has nothing to do with it. It's the version of the .NET Framework that you have installed that matters, and that - even the SDK - is independent of VS.NET. Obviously 2002 will install .NET 1.0 and 2003 will install .NET 1.1.
Also, just a little CPU-time saving tip: ListViewItem.Text == ListViewItem.SubItems[0].Text
As for the problem, you've got me there. I would suggest debugging your code and examining the protected Events property of the ListView (inheritted from Component , so you may have to walk up the derivation stack in the debugger) and see if somehow there are two handlers. I don't even think that's possible, though, since even a new delegate to the same method is "referentially" equal to an existing delegate pointing to the method.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath,
Thanks for the advice, but I don't have time to play with this. So, a bit of playing is necessary. I set an int that is checked everytime the listView is clicked, if it doesn't match the focuseditem.index, it fires off the code you listed first. Otherwise it does nothing.
Written well? No.
Works? Yes.
Thanks again!
|
|
|
|
|
Sorry I can't be of more help. I'm not sure why you're getting this problem. You might double check to make sure that you have any .NET service packs (only SP2 for .NET 1.0 available now until XP SP2 is released - an SP for both 1.0 and 1.1 will be required) and your system is patched. Probably won't help, but I don't know what else to tell you. In such a case - as painful as it may be - hacks are necessary (until the real problem is found).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Add an event handler to SubItemClicked. Access an item's text using this:
this.listviewObject.Items[itemIndex].SubItems[subItemIndex].Text
Kuphryn
|
|
|
|
|
There is no SubItemClicked event for either the ListView or any other class in the .NET Framework Class Library. Perhaps for a third-party control, but not for System.Windows.Forms.ListView, System.Windows.Forms .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hello. I need to show a message in a Windows Forms application. I was thinking in a ListBox.
I did some tests and I know how to show the message in a Console application. Just doint:
public class Message: MarshalByRefObject
{
public void Show(string s)
{
Console.WriteLine(s);
}
}
That works because it's easy to write in the standard output. The doubt is how to write in a component.
Can you help me?
Regards,
Diego F.
|
|
|
|
|
What exactly are you trying to do and where do you want this message displayed? If your remoting object is hosted by a console application with a loop to keep it from terminating, you can use the Console class at any time anywhere in your code, but it will be output on the remote host (i.e., server).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
What I need is a Windows Application that is continuously running and receiving messages. I want to show these messages in a ListBox. My question is how can I write the remote object to show the messages in a ListBox.
I told about the Console because I tried it first with a Console Application, but I'd rather prefer using a Windows app.
Regards,
Diego F.
|
|
|
|
|
Then every time your remote object's method gets call add a new item to the ListBox . Your remote object will need a reference to the ListBox in order to do so, so when your application instantiates the object, pass an instance of the ListBox to its constructor or assign it to a variable.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
The problem with that is that the remote method is called from a Web Service and it can't serialize Windows Forms components. Isn't possible any workaround? My idea was just passing the string.
|
|
|
|
|
Yes, just pass the string but your remote method - the implementation on the server - adds that string as a new ListBox item. That's what I've been trying to say all along. Your Web Service (or whatever client) is making remote calls on your remoting object. That remoting object is the actual implementation and can do about whatever it needs to.
If you were writing a monitor application, for example, your Web Service will call the remote method passing a string. Your remote object's implementation of that method takes that string and adds it to a ListBox in your monitoring application, which needs to pass a reference to the ListBox when it registers the WKO (your remote object).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Just one more doubt.
How do I pass the reference of the ListBox?
I have this:
- The DLL that has the remoting object. That object has a ListBox and a method that adds a string to the ListBox (this is the method called by the web service)
- The web service that has an instance of the remoting class (static)
- The application that receives the messages with the listBox. This application has an instance of the remote object.
- The client application that calls the web method.
This doesn't work because the two remote objects created are not the same, I guess. I tried to write a web method that receives a remote object to use that object, but I get an error.
How can I do that?
I'm finding too much problems here. Maybe I should use a console application instead
|
|
|
|
|
The Remoting object should, for example, accept a ListBox as a parameter in its constructor. When your application that displays the ListBox loads, instantiate the Remoting object passing an instance of the ListBox to which messages are added. You then programmatically register the Remoting object as a WKO, which is discussed in the .NET Remoting documentation in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm sorry but I can't make it work. I tried to follow your instructions:
1) I have the remote object:
public class MessageWin: MarshalByRefObject
{
private string message= "Waiting messages...";
private ListBox l= new ListBox();
public ListBox L
{
set { l = value; }
get { return l;}
}
public string Message
{
get { return message;}
set { message = value;}
}
public void addMessage(string m)
{
mensaje = m;
l.Items.Add(message);
}
}
2) In the client app that should show the messages, just a blank form where I add:
public class Form : System.Windows.Forms.Form
{
private static MessageWin message = new MessageWin(); private System.Windows.Forms.ListBox listBox;
public Form()
{
InitializeComponent();
TcpServerChannel canal = new TcpServerChannel(8989);
ChannelServices.RegisterChannel(canal);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MessageWin),"MessageWin",WellKnownObjectMode.Singleton);
}
// I drag a ListBox from the IDE and change that lines:
private void InitializeComponent()
{
this.listBox = message.L;
[...]
3) In the web service I have that:
public class ServRest : System.Web.Services.WebService
{
private static MessageWin m = new MessageWin();
private void RegisterChannel()
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownClientType(typeof(MessageWin), "tcp://localhost:8989/MessageWin");
}
[WebMethod]
public void sendMessage(string s)
{
m.addMessage(s);
}
4) Just another application that calls the sendMessage web method.
The application doesn't break but no messages are shown in the listBox. I guess the two remote objects are not the same. I tried passing the object to the web service but then I have problems adding the web reference...
Can you help me?
|
|
|
|
|
Again, your remote object class does not instantiate the ListBox but gets a reference to one instantiated and hosted by the Windows Forms application. If the remote object instantiates the ListBox itself, it can't post messages to the one in the Windows Forms application. It's a simple case of control references. You also can't host the ListBox you're incorrectly instantiating in your remote object because it would potentially run on a different thread and you can't add controls created on a different thread to your Form (or other container) when they were created on a different thread.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thank you for keeping helping me.
I don't understand your post. You say that my remote class gets a reference from the Windows forms application, but the code I posted before shows that the remote class creates a new ListBox and the Windows Forms app just gets the remote class one: listBox = message.L;
I think the problem comes because in the web service I declare a new remote object, different from the Windows application one.
What part of my code would you change?
|
|
|
|
|
Yes, the remote object should get an instance of the ListBox declared and initialized in the Windows Forms application. As I mentioned before, if you use the ListBox from the remote object, you could very easily run into many problems since the remote object would be created on a different thread depending on the activation type. Controls cannot host other controls created in a different thread and often times even calling methods or getting/setting properties on controls created in different threads causes problems, which is why Control.Invoke and Control.InvokeRequired exist.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
OK, but I still have the problem. I have 3 applications. I changed my code to pass the ListBox to the remote object, but my web service also needs a remoting object. If I declare a new remote object in the web service, I have two different objects, and I need to work with the same one.
How can I do that? What do I have to change in the web service?
|
|
|
|
|
This is a very simple problem that you're making way to hard and making me repeat myself far too many times.
The remote object is hosted by the monitor application (or whatever it is). It IS the implementation. All other remoting clients - like your web service - simply proxy calls to the remoting object that adds strings to the ListBox declared and instantiated in your Windows Forms application. That application is what is hosting the remoting object. The web service - or any client app using the proxy - doesn't need to have a ListBox at all. It proxies calls to the remoting object via a shared interface or a generated proxy using soapsuds.exe or something. There's absolutely no reason to host the remoting object implementation separate from your monitor application.
Microsoft MVP, Visual C#
My Articles
|
|
|
|