|
This is a continuation of Winforms custom property fails to reload - edited[^]. I'm moving it here (a) because the question with different things retried was getting too big and complex, and (b) this format allows for better discussion of the issue.
So, I have changed my code so that each Control object implements ISerializable. The property I am trying to populate is a member of my Component derived object and looks like this:
private DialogControls _controls = new DialogControls();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Editor(typeof(ControlsEditor), typeof(UITypeEditor))]
[Category("Controls")]
[Description("A list of controls that are added to the dialog")]
public DialogControls Controls {
get { return _controls; }
set { _controls = value; }
}
bool ShouldSerializeControls() { return Controls.Count > 0; }
void ResetControls() { Controls.Clear(); Controls.ProminentIndex = -1; }
The ControlGroup and DialogControls objects:
[Serializable]
public class ControlGroup : IList<Control>, ICollection, ISerializable {
public ControlGroup() { }
List<Control> _controls = new List<Control>();
#region IList<Control>, ICollection implementation
#endregion
#region ISerializable
public ControlGroup(SerializationInfo info, StreamingContext context) {
Control[] controls = (Control[])info.GetValue("controls", typeof(Control[]));
_controls.AddRange(controls);
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("controls", _controls.ToArray());
}
#endregion
}
[Serializable]
public class DialogControls : ControlGroup, ISerializable {
public DialogControls() { }
public int ProminentIndex { get; set; } = -1;
public Control ProminentControl { get { return ProminentIndex >= 0 ? this[ProminentIndex + 1] : null; } }
#region ISerializable
public DialogControls(SerializationInfo info, StreamingContext context) : base(info, context) {
ProminentIndex = info.GetInt32("prominent");
}
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
base.GetObjectData(info, context);
info.AddValue("prominent", ProminentIndex);
}
#endregion
}
The above is now where the problem occurs. The ControlGroup seems to get serialised, but the individual Control objects do not. Once deserialised, I get an array of nulls.
My Control objects look like this:
[Serializable]
public abstract class Control : ISerializable {
protected const ControlState DefaultState = ControlState.Enabled | ControlState.Visible;
public Control() { }
protected Control(Control other) {
_state = other._state;
}
internal CommonFileDialog _dlg = null;
internal IFileDialogCustomize fdc { get { return (IFileDialogCustomize)_dlg?._pDialog; } }
uint _id = 0;
public uint ID { get { return _id; } internal set { _id = value; } }
protected ControlState _state = DefaultState;
public ControlState State {
get {
fdc?.GetControlState(ID, out _state);
return _state;
}
set {
_state = value;
fdc?.SetControlState(ID, _state);
}
}
internal abstract void AddToDialog(CommonFileDialog owner);
internal abstract bool CanMakeProminent { get; }
internal abstract string Value { get; }
internal abstract string Description { get; }
internal abstract string Type { get; }
public abstract Control Clone();
#region ISerializable
public Control(SerializationInfo info, StreamingContext context) {
_state = (ControlState)info.GetValue("state", typeof(ControlState));
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("state", State);
}
#endregion
}
I then inherit each of the controls (there are a dozen of them, but they all follow the same pattern) like this:
[Serializable]
public sealed class CheckBox : Control, ISerializable {
string _label;
public string Label {
get {
return _label;
}
set {
_label = value;
fdc?.SetControlLabel(ID, _label);
}
}
internal bool _checked;
public bool Checked {
get {
return _checked;
}
set {
_checked = value;
fdc?.SetCheckButtonState(ID, _checked);
}
}
public CheckBox() { }
CheckBox(CheckBox other) : base(other) { _label = other._label; _checked = other._checked; }
public CheckBox(string label, bool check) {
Label = label;
Checked = check;
}
#region ISerializable
public CheckBox(SerializationInfo info, StreamingContext context) : base(info, context) {
_label = info.GetString("label");
_checked = info.GetBoolean("checked");
}
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
base.GetObjectData(info, context);
info.AddValue("label", _label);
info.AddValue("checked", _checked);
}
#endregion
#region Control overrides
internal override void AddToDialog(CommonFileDialog dlg) {
}
internal override bool CanMakeProminent { get { return true; } }
internal override string Type { get; } = "CheckBox";
internal override string Description { get { return Label; } }
internal override string Value { get { return Checked.ToString(); } }
public override Control Clone() { return new CheckBox(this); }
public override string ToString() {
return string.Format("{0}({1}, {2})", Type, Description, Value);
}
#endregion
}
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
I'm not clear on what you "think" you are serializing / deserializing.
You've have "getters" without "setters"; which will never serialize, for example.
And no default constructors (apparently) in some cases; which may be needed depending on the type of serialization.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Yes, all objects do have default constructors, and the serialization does not touch the properties that have the getters without setters - I am only using custom serializers.
It should be serializing an array of objects derived from Control.
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
I see.
Well, I "love" my xml. My first impulse would have been to try the following:
Designer Serialization Overview
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Ah-ha! Good link. I'd not found that one previously. I'll have a good read, and see if I can get a solution from there.
Ta much.
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
Another clue:
I modified the ControlGroup serialisation so that it serialises the list of control objects into a byte array, each control being serialised individually, like so:
public ControlGroup(SerializationInfo info, StreamingContext context) {
BinaryFormatter fmt = new BinaryFormatter();
byte[] data = (byte[])info.GetValue("controls", typeof(byte[]));
int count = info.GetInt32("count");
using (MemoryStream ms = new MemoryStream(data)) {
for (int i = 0; i < count; ++i) {
object obj = fmt.Deserialize(ms);
_controls.Add((Control)obj);
}
}
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
BinaryFormatter fmt = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream()) {
foreach (Control c in _controls) {
fmt.Serialize(ms, c);
}
info.AddValue("controls", ms.ToArray());
}
info.AddValue("count", _controls.Count);
}
When I try to reopen the test form with values set, it tells me that type CheckBox cannot be cast to type Control. However, if I close and reopen VS, or at runtime, it deserialises OK. I even put in a messagebox to tell me if obj is Control - I get "True" on compile, but "False" in designer.
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
modified 18-Jan-17 10:56am.
|
|
|
|
|
In a multi-threaded environment, we must take of concurrent access to writable resources. A common approach is to use Monitor or its shorthand form lock .
Task is at a different abstraction level than Thread . A task may run on a thread of its own (and according to the logs, they do so in our application), but that is not guaranteed. See e.g. c# - What is the difference between task and thread? - Stack Overflow[^]:
If the value you are waiting for comes from the filesystem or a database or the network, then there is no need for a thread to sit around and wait for the data when it can be servicing other requests. Instead, the Task might register a callback to receive the value(s) when they're ready. That is, that kind of Task somehow shares a Thread with other running code (I must admit that I do not understand how that works in detail, currently it looks to me like a specialization of the "famous" DoEvents ).
Consequently, Monitor won't be able to distinguish between them, and - because Monitor can be re-entrant - allow both of them access the resource. That is, Monitor "fails".
Examples with Thread s typically use Monitor nonetheless. So I want to ask how I can be sure that Monitor is safe with a Task (or: how can I be sure that a Task is running on a Thread of its own).
|
|
|
|
|
Well, you could supply a custom TaskScheduler implementation that creates a new Thread every time but that seems to be a bit overkill. Alternatively, you can use the Interlocked class to lock access to whatever needs to be done on a one at a time basis.
private int locked = 0;
private void SomeMethod()
{
try
{
if (Interlocked.CompareExchange(ref locked, 1, 0) != 0)
{
return;
}
}
finally
{
Interlocked.Exchange(ref locked, 0);
}
}
This space for rent
|
|
|
|
|
Thanks for your hints. A custom TaskScheduler is overkill, and would also abolish the advantages of the "normal" scheduler.
As for alternatives, I know that they exist.
|
|
|
|
|
|
That article series looks interesting. I know that there are alternatives to Monitor, but Monitor - or rather the lock statement - is most convenient.
Perhaps I should try a different wording of my original question: why do developers not care for the fact that there seem to be cases when Monitor is not applicable with Task?
|
|
|
|
|
I suspect that some developers don't care enough to know that it doesn't work in every case. That would require them to read up on the topic and think about it - the number of times I have heard someone say that a Task creates a new Thread is beyond belief.
This space for rent
|
|
|
|
|
I have a group of checkboxes that need their values checked on submissions. I can't find a convenient way to group them in MVC. Here's what i have in the markup:
<th>Role:</th>
</tr>
<tr>
<th>Booker:</th>
<td>@Html.CheckBoxFor(m => m.Booker)</td>
<th>OA:</th>
<td>@Html.CheckBoxFor(m => m.OA)</td>
<th>Hauler:</th>
<td>@Html.CheckBoxFor(m => m.Hauler)</td>
<th>DA:</th>
<td>@Html.CheckBoxFor(m => m.DA)</td>
</tr>
<tr>
<th>Booker Only:</th>
<td>@Html.CheckBoxFor(m => m.BAO)</td>
<th>OA Only:</th>
<td>@Html.CheckBoxFor(m => m.OAO)</td>
<th>DA Only:</th>
<td>@Html.CheckBoxFor(m => m.DAO)</td>
Later on, I'm attempting to send a message to the screen letting the user know AT LEAST one of the boxes must be checked:
<script type="text/javascript" language="javascript">
function showDialog() {
var ddlValue = $("#ddlPostingMonth").val();
var ChkBooker = $('#Booker').prop("checked");
var ChkOA = $('#OA').prop("checked");
var ChkHauler = $('#Hauler').prop("checked");
var ChkDA = $('#DA').prop("checked");
var ChkBAO = $('#BAO').prop("checked");
var ChkOAO = $('#OAO').prop("checked");
var ChkDAO = $('#DAO').prop("checked");
alert("This is the value: " + ChkBooker);
if (ddlValue == "")
{ $('#dialog').data("kendoDialog").open(); }
if (ChkBooker,ChkOA == false)
{ $('#dialog').data("kendoDialog").open(); }
else {
$.post('SaveAgentInfo', $('#AgentDetailsForm').serialize(), function (data) {
console.log(data);
});
@*document.location = '@Url.Action("SaveAgentInfo", "Agent", new { master_OrderNum = item.Master_OrderNum })';*@
}
}
I've thrown this around in my mind brand for about an hour. I only need ONE box to be checked!! How can I accomplish this and ignore the other boxes if ONE is checked?
Thanks!
-Frustrated Programmer
|
|
|
|
|
Is it "at least One" or "Only One"?
If only one, consider using Radio Buttons; i.e. only one is "selectable" in a group.
If at least one (and maybe more), consider a multi-select list box; or check boxes (with extra code).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
More than one box can be selected. Guess I'll look into the multi-select list box because I'm about to go crazy dealing with this issue.
|
|
|
|
|
If it's just a matter of knowing at any given time if any checkbox is checked, you can do the following:
bool ok = cb1.Checked || cb2.Checked || cb3.Checked || etc.
if ok is true, then at least 1 checkbox was checked; you don't have to repeat the "if's" elsewhere.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
How about using jQuery's .is() filter[^]:
var atLeastOneChecked = $('#Booker, #OA, #Hauler, #DA, #BAO, #OAO, #DAO').is(':checked');
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming,
That was EXACTLY what I needed! Now, all is well!! Thank you so much, Sir!
|
|
|
|
|
I'm trying to convert an old vb.net program into CSharp but I'm having some trouble accessing an unmanaged DLL - the DLL itself is for a NFS reader (CR95HF Demo Kit) and the application note is here:
[^] (a PDF file)
Just as an example I'm trying to access the gethardwareVersion function.
The problem I have is that the example says the declaration should look like
CR95HFDLL_getHardwareVersion(char* StringReply)
and the source that calls this is
char strAnswer[50]="";
int iresult
iresult = CR95HFDLL_GetHardwareVersion(strAnswer)
So far I have:
<pre>namespace RWH_DLL
{
public class RWH
{
[DllImport("CR95HF.dll")]
public static extern UInt32 CR95HFDLL_USBconnect();
[DllImport("CR95HF.dll")]
public static unsafe extern UInt32 CR95HFDLL_getHardwareVersion(char* returnString);
}
}
namespace ReadWriteHardware
{
public partial class RWHardware
{
static RWHardware singleInstance = null;
static readonly object padlock = new object();
RWHardware()
{ }
public static RWHardware Instance
{
get
{
lock (padlock)
{
if (singleInstance == null)
{
singleInstance = new RWHardware();
}
return singleInstance;
}
}
}
}
public partial class RWHardware
{
}
public partial class RWHardware
{
public Boolean GetRWBoard()
{
UInt32 blob = 0;
blob = RWH_DLL.RWH.CR95HFDLL_USBconnect();
String cmdString = "260100";
String rtnString = new string(Convert.ToChar(" "), 256);
char[] strAnswer = new char [50];
blob = RWH_DLL.RWH.CR95HFDLL_getHardwareVersion(strAnswer);
return false;
}
}
}
I'm struggling swapping between the pointers and the char arrays. I have had simpler functions from the dll working (those that just return a value and have no input). - the stuff in comments is all the functions I am converting and my vb versions of those functions.
|
|
|
|
|
You need to convert your managed char array into a pointer that is safe for the unmanaged code to use. To do this, you need to use the fixed keywords when you call the function
char[] strAnswer = new char [50];
fixed(char* pArray = strAnswer) {
blob = RWH_DLL.RWH.CR95HFDLL_getHardwareVersion(pArray);
}
return false;
you will have to also declare the GetRWBoard method as unsafe
Having said this, I prefer to use unmanaged memory when calling into native functions, and utilise the Marshal class for copying the data into managed memory. As such, I would write the routine as:
public static extern UInt32 CR95HFDLL_getHardwareVersion(IntPtr returnString);
IntPtr returnString = Marshal.AllocHGlobal(50);
blob = RWH_DLL.RWH.CR95HFDLL_getHardwareVersion(returnString);
string strAnswer = Marshal.PtrToStringANSI(returnString);
char[] arryAnswer = new char[50];
Marshal.Copy(returnString, arryAnswer, 0, 50);
Marshal.FreeHGlobal(returnString);
return false;
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
Absolutely perfect, works like a charm! (I'm using the marshal version)- the only tiny thing is that
PtrToStringANSI should be
PtrToStringAnsi .
for anyone else reading this solution, I used code like
string commandString = "260100";
IntPtr cmdString = Marshal.StringToHGlobalAnsi(commandString);
blob = RWH_DLL.RWH.CR95HFDll_SendReceive(cmdString, returnString);
to enter commands into the dll.
|
|
|
|
|
Also take a look at http://www.pinvoke.net - they show many examples for common Windows functions. Some of them may have similar signatures like the functions you require, so you can use their way of invoking them.
|
|
|
|
|
Hello there, I need to do the same thing, I'm trying to import the C or VB DLL into C#, but it's the first time that I try to do a similar thing.. Any suggestions for where to start?
My task is really simple, I just have to Detect another NFC tag and then to Write and Read one message.
Did you finish successfully your task? Or it's better to use another NFC tag reader with available C# DLL?
Greetings Davide.
|
|
|
|
|
Hello forum,
actually i'm trying to build my first C# GUI and first C# program ever.
I used Glade to design the GUI. But after compiling and debug-run i'm getting:
/usr/bin/mono --debug --debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:55555,setpgid=y /home/sascha/RiderProjects/PublicanCreators/PublicanCreators/bin/Debug/PublicanCreators.exe
Gtk-Message: (for origin information, set GTK_DEBUG): failed to retrieve property `gtk-primary-button-warps-slider' of type `gboolean' from rc file value "((GString*) 0x20b82e0)" of type `gboolean'
(PublicanCreators:7404): libglade-WARNING **: Expected <glade-interface>. Got <interface>.
(PublicanCreators:7404): libglade-WARNING **: did not finish in PARSER_FINISH state
(PublicanCreators:7404): libglade-CRITICAL **: glade_xml_get_widget: assertion 'self != NULL' failed
(PublicanCreators:7404): libglade-CRITICAL **: glade_xml_get_widget: assertion 'self != NULL' failed
(PublicanCreators:7404): libglade-CRITICAL **: glade_xml_get_widget: assertion 'self != NULL' failed
(PublicanCreators:7404): libglade-CRITICAL **: glade_xml_get_widget: assertion 'self != NULL' failed
(PublicanCreators:7404): libglade-CRITICAL **: glade_xml_signal_autoconnect_full: assertion 'self != NULL' failed
The gui.glade can be found there: PublicanCreators/gui.glade at master · saigkill/PublicanCreators · GitHub[^]
Can anyone help me to get the GUI running, please?
Greetings
Sascha
|
|
|
|
|
I found it out, why it doesn't work. The Glade file was produced with Glade 3.x. My implementation was for using with the old libglade library. But since some time this library was replaced by Gtk.Builder. This one can now handle the Glade 3.x output.
If anyone has such problem again, so you can start there with your journey: GtkSharp - Part 3 - Basic Example with VS and Glade - The Grbd Blog[^]
|
|
|
|
|