Thursday, October 21, 2010

DataGridView virtual mode with custom control race condition fix

This is for when you have a DataGridView in virtual mode in which you have both unbound and bound columns which depend on each other. It went wrong when editing the cells.
I found out that I got a race condition. I then checked the stacktrace:

- MyGridView.OnCellValueNeeded(System.Windows.Forms.DataGridViewCellValueEventArgs e)
- System.Windows.Forms.DataGridView.OnCellValueNeeded(int columnIndex, int rowIndex)
- System.Windows.Forms.DataGridViewCell.GetValue(int rowIndex)
- DataGridViewControlCell.GetValue(int rowIndex)
- System.Windows.Forms.DataGridView.OnCellValidating(ref System.Windows.Forms.DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, System.Windows.Forms.DataGridViewDataErrorContexts context)
- System.Windows.Forms.DataGridView.CommitEdit(ref System.Windows.Forms.DataGridViewCell dataGridViewCurrentCell, System.Windows.Forms.DataGridViewDataErrorContexts context, System.Windows.Forms.DataGridView.DataGridViewValidateCellInternal validateCell, bool fireCellLeave, bool fireCellEnter, bool fireRowLeave, bool fireRowEnter, bool fireLeave)
- System.Windows.Forms.DataGridView.CommitEdit(System.Windows.Forms.DataGridViewDataErrorContexts context, bool forCurrentCellChange, bool forCurrentRowChange)



So it tried getting the value for the cell that was currently being edited !
I fixed it in MyGridView (called with base.OnCellValueNeeded):

        protected override void OnCellValueNeeded(DataGridViewCellValueEventArgs e)
        {
            if (Columns[e.ColumnIndex] is DataGridViewControlColumn)
            {
                /*
                 * Special check to prevent race condition. Call this method first like this:
                 *    base.OnCellValueNeeded(e);
                 *    if (e.Value != null) return;
                 */
                if (Rows[e.RowIndex].Cells[e.ColumnIndex].IsInEditMode)        // editing control present?
                {
                    if ((EditingControl as TControl).EditingControlRowIndex == e.RowIndex)        // make sure it's the correct row
                    {
                        if ((EditingControl as TControl).EditingControlValueChanged)    // prevent re-use of old editing control
                        {
                            e.Value = (EditingControl as TControl).EditingControlFormattedValue;    // use value from editing control
                            return;
                        }
                    }
                }
            }
             base.OnCellValueNeeded(e);
        }

 Hopefully, you find this a bit useful.

Wednesday, October 06, 2010

iPhone native internet tethering (4.0.1)

When I was on 3.1.2 I had native internet tethering working without much problems. Just use ultrasn0w or other unlock hack and install any carrier profile to make the switch visible.
There was no real need to patch the CommCenter executable.
The CommCenter patches were initially released as plain patchfiles that required entering shell commands, but later appeared in Cydia repositories too.
With 4.0.1, it is required to do it this way. So you don't need an unlock hack installed per say. The CommCenter patch can be found in some shady repository you might need to add. (Try searching on myrepospace.com)
The CommCenter patch makes it accept any non-matching signature in the carrier bundle.
Anyway, it is not that difficult and can be read about on other sites. I got all the handy tools on my iPhone already (ssh with changed passwords, vim), so here's what I did... (you should use FTP if you don't want to mess with SSH)

ssh root@yourphone
cd /var/mobile/Library/Carrier\ Bundle.bundle
plutil -convert xml1 carrier.plist
vim carrier.plist


Under <key>apn</key><string>mms</string>
I changed
<key>type-mask</key><integer>53</integer>

Google for typemask.png to see what bits to toggle.
Don't forget to make a backup of the file if you are unsure.
Then, for some reason you need to reset the network settings. Perhaps it just updates /var/mobile/Library/Preferences/com.apple.carrier.plist I don't know exactly yet)
Perhaps you could try killall CommCenter SpringBoard too.
Btw, The directory is actually a symbolic link and the files in it gets updated occasionally by Apple. It will ask you however before doing that.
To recreate, use something like: ln -s /System/Library/Carrier Bundles/TMobile_nl.bundle /var/mobile/Library/Carrier\ Bundle.bundle

While MyWi (in Cydia) offers internet tethering too, it got it's limitations (but is being worked on). e.g. it cannot connect via bluetooth to a laptop. Also, it costs a bit of money.

NOTE: Your mobile provider probably does not accept free internet tethering.