How to get access to generated text box inside Silverlight DataForm? - silverlight

I have a DataForm bound to a simple object that has some text fields. The DataForm correctly auto generates a TextBox for each of the string fields. From code I now need to set the focus to one of those generated TextBox elemetns. How do you get the generated element from the DataForm so I can set focus to it?

Use AutoGeneratingField event of DataForm.
Here is example how to get property with name ID
void dataForm1_AutoGeneratingField(object sender, DataFormAutoGeneratingFieldEventArgs e)
{
if (e.PropertyName == "ID")
{
// set focus
}
}

Related

WPF SelectedItem binding to source doesn't affect keyboard navigation

OK, so I'm using a typical Binding to my ViewModel. It works beautifully, to source or to target, or so it seems. The vm collection is an ObservableCollection which is initialized and never modified (no setter).
public ObservableCollection<Statement> StatementsList { get; } = new();
#region SelectedStatement
private Statement _selectedStatement;
public Statement SelectedStatement
{
get => _selectedStatement;
set => Set(ref _selectedStatement, value, nameof(SelectedStatement));
}
#endregion SelectedStatement
I can set SelectedStatement from the ViewModel, and the UI updates fine. I can watch the SelectionChanged event of the DataGrid and confirm the added items and removed items are exactly as expected.
Then, I select a different row USING THE MOUSE, and use my search function to select another row using SelectedItem = some statement, which visually selects the row perfectly (again), confirmed by the SelectionChanged event again. SelectedStatement in my view model has the correct value!
Then, the weirdness starts. I press the down arrow the keyboard.
You'd expect the next line after the selected statement to be selected, but instead the next line after the previously selected item (using the mouse) is selected. It's like the keyboard responding code in the DataGrid is not recognizing the prior new row selection via the VM.
Has anyone seen this behavior? I've done WPF development for many years, and I've seen many weird WPF bugs, but this one I've never noticed!
Note that IsSynchronizedWithCurrentItem="True" on the DataGrid. I tried setting it to false just as a stab in the dark, but no change in behavior. I also tried changing my SelectedItem property to wrap a call to GetDefaultCollectionView() and getting/changing the selected item via the collection view instead of using a binding to SelectedItem. The behavior is identical.
Selecting an item is essentially setting IsSelected = true.
And setting this property does not affect the Focus transition to the selected element in any way.
And when controlling from the keyboard, the transition occurs from the element with Focus.
You can add the SelectionChanged processing to the Selector (ListBox, DataGrid,...) and in it perform the Focus transition to the selected item (by the index in the SelectedIndex).
An example of such a handler:
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is Selector selector)
{
int index = selector.SelectedIndex;
if (index >=0)
{
var element = selector.ItemContainerGenerator.ContainerFromIndex(index);
if (element is UIElement uiElement)
uiElement.Focus();
}
}
}

dynamic tooltips on Winforms controls

I am looking for the cleanest way to bind the same datasource to a control's tooltip that I am binding to the control itself. For example, I have the line
control.DataBindings.Add(new Binding("EditValue", dataFeatures, "Key", true));
where dataFeatures is of type BindingSource. I repeat similar lines for many controls on a WinForm Form. Some of these controls can adopt values whose text can span a greater text width than what is visible within the control itself. Instead of redesigning the layout of the form to account for the possibility of partially hidden text in some controls in a few situations, I would like to have the tooltip of each control be bound to the same property of the BindingSource as the controls' EditValue or Text property. Is this possible? I can imagine there is a way to do it by hand by handling the EditValueChanged event like I already do for different reasons, but I was hoping there would be a cleaner solution than having to add new lines of code for each control.
Anybody have a suggestion?
Thanks!
0. For DevExpress controls you can just bind DevExpressControl.ToolTip property to the same value:
devExpressControl.DataBindings.Add(new Binding("EditValue", dataFeatures, "Key", true));
devExpressControl.DataBindings.Add(new Binding("ToolTip", dataFeatures, "Key", true, DataSourceUpdateMode.Never));
1. For standard WinForms controls you can use System.Windows.Forms.ToolTip component and its ToolTip.Popup event. For each control set its ToolTip to some value otherwise ToolTip will never appears:
control.DataBindings.Add(new Binding("Text", dataFeatures, "Key", true));
toolTip1.SetToolTip(control, "Some value");
Now you can use ToolTip.Popup event:
private bool _updatingToolTip;
private void toolTip1_Popup(object sender, PopupEventArgs e)
{
if (_updatingToolTip) return;
//Get binding for Text property.
var binding = e.AssociatedControl.DataBindings["Text"];
if (binding == null) return;
//Get binding value.
var manager = binding.BindingManagerBase;
var itemProperty = manager.GetItemProperties().Find(binding.BindingMemberInfo.BindingField, true);
object value = itemProperty.GetValue(manager.Current);
string toolTipText;
if (value == null || string.IsNullOrEmpty(toolTipText = value.ToString()))
{
e.Cancel = true;
return;
}
//Update ToolTip text.
_updatingToolTip = true;
toolTip1.SetToolTip(e.AssociatedControl, toolTipText);
_updatingToolTip = false;
}
You can easily implement dynamic tooltips with the ToolTipController component. Put this component onto the Form, and assign to each editor via the BaseControl.ToolTipController property.
When it is done, you can handle the ToolTipController.BeforeShow event and change the text according to the control state. The active control is passed through the SelectedControl property of the event parameter.

How can i get the clicked button's row values on silverlight telerik radgridview button column?

I have a hyperlink button colum in silverlight telerik radgridview, as a cell template.
I am using MVVM.
When i click on the hyperlink button, how can i get its row's values(atleast in the code behind)..?
Thanks in advance..
You need to use the ParentOfType extension method to get hold of the row containing the button.
Once you have the row you can cast the item type to your viewmodel and access the properties of it.
Make sure you have a using statement for the extension method:
using Telerik.Windows.Controls;
private void Button_Click(object sender, RoutedEventArgs e)
{
var parent = (sender as Button).ParentOfType<GridViewRow>();
var rowVM = parent.Item as YourVmClass;
}
If you are using MVVM you can also use the EventToCommandBehavior.
This allows you to execute all events as commands. You can then handle the command in your viewmodel.

Silverlight: Copy/Paste Context Menu with TextBox (Text Highlighting Issue)

I have created a TextBox control:
public class MyTextbox : TextBox
which is a just a normal TextBox, to which I have added a behavior that I have written:
public class TextBoxCutCopyPasteBehavior : Behavior<TextBox>
Everything works fine and dandy: right-clicking will display a ContextMenu with Cut, Copy, Paste options. However, the TextBox text ceases to be highlighted at that point, since the TextBox has lost focus.
What would the best way be to make the selected text remain highlighted, even after the ContextMenu appears and the TextBox loses focus?
Thank you so much for all of your help!
You should still be able to access the SelectedText property of the TextBox
private void CopyMenuItem_Click(object sender, RoutedEventArgs e)
{
string textToCopy = MyTextBox.SelectedText;
// do something
}

How can I put a Silverlight 3 DataGridCell into edit mode in code?

I want to be able to pick a specific cell in a Silverlight 3.0 DataGrid and put it into edit mode. I can use the VisualTreeManager to locate the cell. How do I switch to edit mode?
Each DataGridCell looks like this in the VisualTreeManager:
System.Windows.Controls.DataGridCell
System.Windows.Controls.Grid
System.Windows.Shapes.Rectangle
System.Windows.Controls.ContentPresenter
System.Windows.Controls.TextBlock
System.Windows.Shapes.Rectangle
System.Windows.Shapes.Rectangle
with the TextBlock containing the text I want to edit.
Update
Following #AnthonyWJones' suggestion, here's how I tried to do this using BeginEdit().
I wanted to keep it simple so I thought I'd pick a column in the first row. Even that proved beyond my SL knowledge! In the end, I get the first row by creating a field called firstRow to hold it:
private DataGridRow firstRow;
added a LoadingRow handler to the DataGrid:
LoadingRow="computersDataGrid_LoadingRow"
and
private void computersDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
if (this.firstRow == null)
this.firstRow = e.Row;
}
and then adding a button to the panel to trigger the edit:
private void Button_Click(object sender, RoutedEventArgs e)
{
this.dataGrid.SelectedItem = this.firstRow;
this.dataGrid.CurrentColumn = this.dataGrid.Columns[4];
this.dataGrid.BeginEdit();
}
I click the button and the correct cell is selected but it doesn't go into edit on the cell. It takes a manual click to achieve that.
I'm not sure why you need to find the DataGridCell using VisualTreeManager nor do I know currently how you would properly start editing . You may get away with simply setting the cell's visual state to editing.
VisualStateManager.GoToState(myDataGridCell, "Editing", true);
I'm not sure how the grid behaves when you do something like the above. You may find things goe a bit pearshaped if you need DataGrid to help you revert changes to a row.
The "standard" approach would be to set the DataGrid SelectedItem property to the item represented by the row, set the CurrrentColum property to the DataGridColumn object that represents to the column in which the cell is found. Then call the BeginEdit method.
I am not able to understand your problem properly, but I had a similar problem
I wanted to make only few of the Grid Cells editable and rest were not. Instead of creating a logic and assigning ReadOnly as true/ false, I did the simple thing.
Mark the whole Grid's cells are writable, IsReadOnly as false
Set the event PreparingCellForEdit and send a callback
When you double click on a cell, it gets in the edit mode
Check whether this cell you want to be editable
If it is allowed to be edited, go ahead
If that cell is ReadOnly, then call CancelEdit
The sample code goes like
namespace foo
{
public class foobar
{
public foobar()
{
sampleGrid = new DataGrid();
sampleGrid.IsReadOnly = false;
sampleGrid.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(sampleGrid_PreparingCellForEdit);
}
void sampleGrid_PreparingCellForEdit(object sender, DataGridsampleGrid_PreparingCellForEditEventArgs e)
{
if (sampleGrid.SelectedItem != null)
{
bool isWritableField = CheckIfWritable()
if (isWritableField == false)
{
sampleGrid.CancelEdit();
}
// continue with your logic
}
}
private DataGrid sampleGrid;
}
}

Resources