DevExpress XtraGrid checkbox check not registered unless focus changes - checkbox

We have a databound XtraGrid on our Windows form. One of the columns is a check box. The problem is as follows: when users check the checkbox and click OK button, the checkbox, while visibly checked, is not considered checked by the grid. When I do this (while looping through rows):
isAllowed = Convert.ToBoolean(viewMain.GetRowCellValue(nRowCtr, "IsAllowed"))
I get back False. BUT, if the user checks the box, and then clicks somewhere else on the form or on another row in this grid, thus taking away focus from the checked checkbox, the same code above will return True.
Any insight on how to fix this behavior would be greatly appreciated.
Workaround found:
With default settings, when users click on a cell to edit it, the cell goes into edit mode, loads the editor control (in this case I have a CheckEdit repository control) and changes control's value (in this case checked state). If I click on another row, or another control, the cell then gets out of edit mode, committing the change to data item. But if I click on a button, then my change is lost. The workaround is to use the CheckEdit's CheckedChanged event to close editor:
Private Sub edCheck_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles edCheck.CheckedChanged
gridYears.FocusedView.CloseEditor()
End Sub

There's actually a cleaner way of doing this (it works for all RepositoryItems), detailed on the DevExpress site. The idea is to call the GridView.PostEditor method from a repository item's EditValueChanged event handler to immediately save the edited value to the grid's cell and the underlying column.

This code in the view's CellValueChanging event handler solved the problem:
private void OnCellValueChanging(object sender, CellValueChangedEventArgs e)
{
_gridView.SetFocusedRowCellValue(_gridView.FocusedColumn, e.Value);
}

Related

How to focus on a ToolStripTextBox (one of the items in a ToolStripDropDownButton.DropDownItems collection) when the drop down opens

I'm building the DropDownItems of a ToolStripDropDownButton programmatically. The first field is always a ToolStripTextBox (which users can type into to filter the following items). I want the ToolStripTextBox to have focus as soon as the drop down opens so that user can:
Click on the ToolStripDropDownButton
Begin typing (to filter the items)
However, when I try to focus on the ToolStripTextBox (within the DropDownOpened event handler):
Dim v As ToolStripTextBox = DirectCast(tsbForms.DropDownItems(0), ToolStripTextBox)
Me.ActiveControl = v.Control
I get an exception:
System.ArgumentException: 'Invisible or disabled control cannot be activated'
Here's a screen shot of the dropdown so you can see what I'm talking about:
Currently the textbox at the top doesn't have focus and you have to click in it before you can start typing in the filter.
FYI I've tried testing the Visibility of the ToolStripTextBox before setting ActiveControl and it is True in this event. I've tried performing the operation a few other events and got the same result.
Just setting focus worked for me:
Dim v As ToolStripTextBox = DirectCast(tsbForms.DropDownItems(0), ToolStripTextBox)
v.Focus()
I used the DropDownOpened event of the parent ToolStripDropDownButton.

WPF DataContext issue with datacontext object

I have created a simple sample with datacontext. Please get the sample from here : source I understand that the uses of DataContext is
If the user change any content in UI, it should be updated in the back end datacontext class without any additional work.
If we make any change in back end datacontext object, it should be updated in UI without any additional work.
In my sample,
If I click "click" button, the textbox value gets updated. - pass
If I click "update" button, the textbox value gets updated. - pass
If I click "clear" button, the textbox value not updated. - fail
After clicked "clear" button, If "click" or "update" button is clicked the textbox value not updated. - fail
Am I doing anything wrong? If yes, how can I initialize some value in the textbox in constructor, and after that if the user make changes, the datacontext object values need to be updated. If I update any value in code behind, the values need to updated in UI. Also if I click "clear" button all the textbox values need to be cleared. After that if user enter value again, the object need to update. How can I achieve it? Please help.
Note: In my sample I have commented some lines. In that i have casted the datacontext to the model class every time and changed it. Its working fine. Do i need to use that method to update values run time. Changing values in object will not update in UI?
The problem is that you consider the variable 'dc' linked to the DataContext, but that is not the case. To fix your code simply set the DataContext again after you change the 'dc' variable.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
dc = new Journal();
myPanel.DataContext = dc;
//myPanel.DataContext = new Journal();
}

WPF Tab_selectionChanged

I have this strange issue I am facing currently.
I have created an WPF application based on WPF page navigation. I have few button and depending on the button click the the user is navigated to respective WPF page.
In these WPF pages I have Tab controls and have used selectionchanged event handler to perform some task.
Now to the issue,
When I try to go a particular page, the selectionchanged event is also executed even before the page is loaded completely, I have tried to use the windows.loaded (based on the answer provided to my previous question - here) - I have no luck.
[I am using WPF Navigation framework]
Somehow the selectionchanged event is executing twice.
How do I stop this from happening?
I think you should check SelectionChange.AddedItems and SelectionChange.RemovedItems to find the difference between these to firings. I guess that when you select a page, SelectionChange.RemovedItems==0 while when you click on a tabItem to select it, SelectionChange.RemovedItems==1. if so just write:
if (SelectionChange.RemovedItems==0)
return;
Edit1: Please see the first comment.
Edit 2
void tablcontrol_SelectionChange(object sender, SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count == 0)
{
// I guess this is the event that happens when a page is selected
// in this case just a TabItem is added to the selection
// and nothing is removed, so do nothing
return;
}
// if you are here, it means that this is another selection changed event
// so Perform those tasks that you mentioned in your question
}

WPF, MVVM and combobox

I am having some trouble with my comboBox logic in my viewModel. The viewModel populates the comboBox and the user can select items.
When an item is selected, some editable info appears in the view and they can make changes. Now, I want to prompt the user to save if changes were made and not saved and they are trying to select another item in the drop down (a "Save?" yes/no/cancel messageBox).
Right now I need to remember the previously selected item and handle this myself by resetting the selected item if the user selects cancel. Since the comboBox does not have a PreviewSelectionChanged event, this is the only way I can think of of handling this scenario. It works but it gets a little messy hwen there are multiple comboBoxes, etc.
Am I missing anything or is this just the way it needs to be done?
You essentially have to make a flag in your view model called isDirty or something along those lines.
public class EditorViewModel
{
private bool _isDirty = false;
private long _editableProperty;
public long EditableProperty
{
get { return _editableProperty; }
set
{
_editableProperty = value;
// We've detected a change so mark this view model as dirty.
_isDirty = true;
}
}
}
Note that you will have to have to jump through a few more hoops if you want ensure that the data is in fact different from your original. So say someone accidently adds a space in EditableProperty and removes it your view model will think it's dirty and prompt the user.
The Windows Forms ComboBox provided a SelectionChangeCommitted event, but for the WPF ComboBox control you correct in that there is no event that will notify before the selection change occurs that will provide you with a means of cancelling the event.
If you are going to take a change tracking/editable approach, I would recommend considering implementing IChangeTracking and IEditableObject on the items in your combobox items source.
You will probably have to handle the SelectionChanged event, inspect the removed items to determine if the item that was previously selected was modified and then display a dialog requesting confirmation. If no/cancel was indicated, you can then set the selected index back to that of the previously selected item.
What about making the Editable item a copy of an item instead of the actual item?
So your ViewModel would contain
ObservableCollection<MyModel> ComboBoxItems;
int SelectedComboBoxIndex;
MyModel EditingItem;
Whenever the PropertyChange event occurs on SelectedComboBoxIndex, you check and see if EditingItem is null or not. If it is null, it means you're safe to switch and you set
EditingItem = ComboBoxItem[SelectedComboBoxIndex]).Copy();
If the EditingItem is not null, then you throw up a prompt asking if the user wants to save changes or cancel.
When the user hits Save, it takes the EditingItem and applies the changes to the data store and updates the item in the ComboBoxItems list.
If they hit Cancel, the EditingItem is simply discarded.

Control.Leave Triggered by MouseDown, not MouseUp

I have a C# .NET WinForm. In the form, I allow a user to add an item to a ListView by double-clicking in the ListView. This adds a TextBox control to the ListView and places the key cursor in the TextBox so a user can type.
I detect that a user is done with an item in a couple of ways (e.g. pressing Enter, Esc, Tab...), but also when they Leave (TextBox.Leave) the TextBox.
The problem is this set of steps:
User triggers TextBox.Leave by mousing down outside of the TextBox.
I add the new item to the ListView.
I select the the new item in the ListView.
Mouse up occurs and the new item that I just selected, loses focus and is unselected.
What I would like is for TextBox.Leave to be triggered by MouseUp, not MouseDown. How can I accomplish this?
Edit: Cody suggests using the ListView.LabelEdit property. Here are my results trying that:
listView_DoubleClick(...) {
listView.LabelEdit = true;
if(double clicked on existing listViewItem) {
listViewItem.BeginEdit(); //this works as expected
} else {
var newItem = listView.Items.Add("");
newItem.BeginEdit(); //this doesn't work, see below
}
}
The call to newItem.BeginEdit() only works when the user double clicks where the new item will show up. If they double click on any other blank area in the listview the new item is added, but it does not enter edit mode. What's going on here?
Pressing the mouse down on another control is causing that other control to request the focus and so the focus moving causes the TextBox.Leave event to occur. Preventing ever other possible control from requesting the focus is not a very viable option. But luckly you only need to prevent the ListView from using the MouseDown to shift focus. So you need to override the WndProc of your ListView and when the MouseDown windows message occurs and you are currently showing a TextBox you eat the message. In order words you do not allow the base class to process it.

Resources