Focus on textBox on the page load with MVVM - c#

I can't set keyboard focus on textbox control when my UI form loads. I am using MVVM pattern and when I tried solution on the following link but this didn't help. When the form loads there is a caret in my textbox but it's not flashing, and I can't write text in it. The same thing happens when I use FocusManager.focused element in XAML. I also tried with Keyboard.Focus(MytextBox) but the same thing happened... Please help anybody, I am stuck 2 days with this...
This is class where i made dependency property IsFocused and used it for binding with isFocused property in my viewmodel:
public static class Attached
{
public static DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(Attached), new UIPropertyMetadata(false, OnIsFocusedChanged));
public static bool GetIsFocused(DependencyObject dependencyObject)
{
return (bool)dependencyObject.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject dependencyObject, bool value)
{
dependencyObject.SetValue(IsFocusedProperty, value);
}
public static void OnIsFocusedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
TextBox textBox = dependencyObject as TextBox;
bool newValue = (bool)dependencyPropertyChangedEventArgs.NewValue;
bool oldValue = (bool)dependencyPropertyChangedEventArgs.OldValue;
Keyboard.Focus(textBox);
if (newValue && !oldValue && !textBox.IsFocused) textBox.Focus();
}
}
This is my XAML:
<TextBox a:Attached.IsFocused="{Binding IsFocused, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}.../>"

For this u can use your code behind file. In the page loaded event you should do
MyTextBox.Focus();

In the Window-Element you can write
FocusManager.FocusedElement="{Binding ElementName=textBox}"

You maybe get a problem with the loaded-timing, meaning you set focus but it gets stolen afterwards. You can try to defer that by using a dispatcher:
myView.Dispatcher.BeginInvoke(new Action(() =>
{
textBox.Focus();
}), DispatcherPriority.ContextIdle);

Related

TreeListControl does not update values of children immediately

I use DevExpress. I have TreeListControl. One column consists Comboboxes (implemented by ComboBoxEditSettings) with several values. When I set a value in Combobox for parent its children will be updated just when I Change Focus or press Enter, but not immidiately.
Here are some Points I have already tried:
Set an Event in ComboBoxEditSettings for an interaction, eg MouseUp;
Set an EventToCommand for eventName EditValueChanged, for example.
Binding is not working;
Set an Event on OkButton_Click, but I have
not found how to get an OkButton_Click Event in Combobox.
Create CustomButton in ComboboxEdit and set a PopUpClose Event. In this
case binding works, but I have not found how to set MyCustomButton
the OkButton Event.
Here is part of my Code. Maybe it helps to understand my case.
<dxg:TreeListControl x:Name="Tree" ItemsSource="{Binding TreeItems, Mode=TwoWay}">
<dxg:TreeListControl.Columns>
<dxg:TreeListColumn FieldName="Node"/>
<dxg:TreeListColumn FieldName="Frequency"/>
<dxg:TreeListColumn.EditSettings>
<dxe:ComboBoxEditSettings ItemsSource="{Binding Samplers}" IsTextEditable="False" DisplayMember="SamplerLongText" ValueMember="SamplerId">
<dxe:ComboBoxEditSettings.StyleSettings>
<dxe:CheckedComboBoxStyleSettings/>
</dxe:ComboBoxEditSettings.StyleSettings>
</dxe:ComboBoxEditSettings>
</dxg:TreeListColumn.EditSettings>
</dxg:TreeListColumn>
</dxg:TreeListControl.Columns>
<dxg:TreeListControl.View>
<dxg:TreeListView
x:Name="TreeListView"
AllowPerPixelScrolling="True"
ShowTotalSummary="True"
KeyFieldName="TreeItemId"
ParentFieldName="ParentId"
ShowCheckboxes="true"
CheckBoxFieldName="IsChecked"
IsCheckBoxEnabledFieldName="IsEnable"
AllowRecursiveNodeChecking="True"
ShowNodeImages="True"
AutoWidth="True"
ImageFieldName="NodeImage"/>
</dxg:TreeListControl.View>
</dxg:TreeListControl>
Thank you in advance!
We have this little helper class for the exact same functionality when using CheckEdits but it should also work for your ComboBoxEdits.
Mind that it utilizes the EditValueChanging-event under the hood which might already answer your question.
public partial class EditorCommitHelper
{
public static readonly DependencyProperty CommitOnValueChangedProperty = DependencyProperty.RegisterAttached("CommitOnValueChanged", typeof(bool), typeof(EditorCommitHelper), new PropertyMetadata(CommitOnValueChangedPropertyChanged));
public static void SetCommitOnValueChanged(GridColumn element, bool value)
{
element.SetValue(CommitOnValueChangedProperty, value);
}
public static bool GetCommitOnValueChanged(GridColumn element)
{
return (bool)element.GetValue(CommitOnValueChangedProperty);
}
private static void CommitOnValueChangedPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
GridColumn col = source as GridColumn;
if (col.View == null)
Dispatcher.CurrentDispatcher.BeginInvoke(new Action<GridColumn, bool>((column, subscribe) => {
ToggleCellValueChanging(column, subscribe);
}), col, (bool)e.NewValue);
else
ToggleCellValueChanging(col, (bool)e.NewValue);
}
private static void ToggleCellValueChanging(GridColumn col, bool subscribe)
{
TreeListView view = col.View as TreeListView;
if (view == null)
return;
if (subscribe)
view.CellValueChanging += new CellValueChangedEventHandler(view_CellValueChanging);
else
view.CellValueChanging -= view_CellValueChanging;
}
static void view_CellValueChanging(object sender, CellValueChangedEventArgs e)
{
TreeListView view = sender as TreeListView;
if ((bool)e.Column.GetValue(CommitOnValueChangedProperty))
view.PostEditor();
}
}
usage:
<dxg:GridColumn Header="your header"
FieldName="your_field"
your_xmlns:EditorCommitHelper.CommitOnValueChanged="True">
</dxg:GridColumn>

Set Focus in VisualStatemanager

I write a custom control and want to set the focus on a control in case a VisualState goes active.
The control is a kind of ComboBox with a search box in the drop down popup. When I open it, the Opened Visual State goes active and the search box should be focused. Besides a dependency property bool IsDropDownOpen will be true.
PS: It's an Windows 10 UWP project.
Sorry, but you can set focus only programmatically, not by visual state :(
Not my favorite solution, but a workaround without accessing the TextBox from code behind.
I implemented an attached property which sets the focus to a control in case the property is set to true.
public class FocusHelper : DependencyObject
{
#region Attached Properties
public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(FocusHelper), new PropertyMetadata(default(bool), OnIsFocusedChanged));
public static bool GetIsFocused(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
#endregion
#region Methods
public static void OnIsFocusedChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
var ctrl = s as Control;
if (ctrl == null)
{
throw new ArgumentException();
}
if ((bool)e.NewValue)
{
ctrl.Focus(FocusState.Keyboard);
}
}
#endregion
}
So I can bind this property to my IsDropDownOpen property. So every time I open the drop down, the TextBox will get the focus.
<TextBox helper:FocusHelper.IsFocused="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" ...

WPF - GetBindingExpression in PropertyChangedCallback of DependencyProperty

I need to be able to access the binding expression for the Text property of a TextBox from within a DependencyProperty on a TextBox. the value of my DependencyProperty is set in XAML. I'm calling GetBindingExpression in the PropertyChangedCallback method of my DependencyProperty, but I'm too early at this point because GetBindingExpression always returns null here, yet after the window fully loads it definitely returns a value (I tested using a button on screen to change the value of my DependencyProperty).
Clearly I have a load order issue here where my DependencyProperty's value is set before the Text property is bound to my view model. My question is, is there some event I can hook into to identify when the binding of the Text property is complete? Preferably without modifying the XAML of my TextBox as I have hundreds of them in the solution.
public class Foobar
{
public static readonly DependencyProperty TestProperty =
DependencyProperty.RegisterAttached(
"Test", typeof(bool), typeof(Foobar),
new UIPropertyMetadata(false, Foobar.TestChanged));
private static void TestChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
var textBox = (TextBox)o;
var expr = textBox.GetBindingExpression(TextBox.TextProperty);
//expr is always null here, but after the window loads it has a value
}
[AttachedPropertyBrowsableForType(typeof(TextBoxBase))]
public static bool GetTest(DependencyObject obj)
{
return (bool)obj.GetValue(Foobar.TestProperty);
}
[AttachedPropertyBrowsableForType(typeof(TextBoxBase))]
public static void SetTest(DependencyObject obj, bool value)
{
obj.SetValue(Foobar.TestProperty, value);
}
}
Try listen to LayoutUpdated event. I think its called layout updated event. Else google it. Its a crazy little event which will be fired everytime no matter what you do ex. when loading, drawing, even when you move your mouse!
Take a look at this pseudo code:
private static void TestChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
var textBox = (TextBox)o;
// start listening
textBox.LayoutUpdated += SomeMethod();
}
private static void SomeMethod(...)
{
// this will be called very very often
var expr = textBox.GetBindingExpression(TextBox.TextProperty);
if(expr != null)
{
// finally you got the value so stop listening
textBox.LayoutUpdated -= SomeMethod();

How can I update the source from a custom control with dependency properties in silverlight?

I've created a custom control that extends the RichTextBox so that I can create a binding for the xaml property. It all works well as long as I just update the property from the viewmodel but when I try to edit in the richtextbox the property is not updated back.
I have the following code in the extended version of the richtextbox.
public static readonly DependencyProperty TextProperty = DependencyProperty.Register ("Text", typeof(string), typeof(BindableRichTextBox), new PropertyMetadata(OnTextPropertyChanged));
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var rtb = d as BindableRichTextBox;
if (rtb == null)
return;
string xaml = null;
if (e.NewValue != null)
{
xaml = e.NewValue as string;
if (xaml == null)
return;
}
rtb.Xaml = xaml ?? string.Empty;
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
In the view I've set the binding like such
<Controls:BindableRichTextBox Text="{Binding XamlText, Mode=TwoWay}"/>
In the viewmodel I've created the XamlText as a normal property with the NotifyPropertyChanged event being called on updates.
I want the bound XamlText to be updated when the user enters texts in the RichTextBox either on lostfocus or directly during edit, it doesn't really matter.
How can I change the code to make this happen?
You will need to listen to changes to the Xaml-property of the BindableRichTextBox and set the Text-property accordingly. There is an answer available here describing how that could be achieved. Using the approach described in that would the result in the following code (untested):
public BindableRichTextBox()
{
this.RegisterForNotification("Xaml", this, (d,e) => ((BindableRichTextBox)d).Text = e.NewValue);
}
public void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
{
var binding = new Binding(propertyName) { Source = element };
var property = DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(UserControl),
new PropertyMetadata(callback));
element.SetBinding(property, binding);
}

WPF DependencyProperty and data binding

I am working on WPF project. I create a usercontrol containing a combobox; which represent boolean value(True or false). And I register a DependencyProperty Value for my usercontrol.
Whenever combobox selection was changed, I will update the Value property and also when Value property is update I will update combobox.
But I found the problem when I use my usercontrol in MVVM. I bind the Value property with my IsEnable property in my viewModel. I set binding mode as TwoWay binding. But when I changed selection in comboBox, IsEnable property is never set.
My usercontrol:
public bool Value
{
get { return (bool)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(bool),
typeof(BooleanComboBox),
new UIPropertyMetadata(true, OnValuePropertyChanged));
private void Cmb_Selection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cmb = sender as ComboBox;
object selectedValue = cmb.SelectedValue;
if (selectedValue == null)
{
this.Value = false;
}
else
{
if (selectedValue.GetType() == typeof(bool))
{
this.Value = (bool)selectedValue;
}
else
{
this.Value = false;
}
}
if (this.OnValueChange != null)
this.OnValueChange(this, this.Value);
}
private static void OnValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
BooleanComboBox self = sender as BooleanComboBox;
self.Cmb_Selection.SelectedValue = (bool)args.NewValue;
}
In window, where I place my usercontrol (I already set usercontrol's datacontext to my viewModel):
<tibsExtControl:BooleanComboBox Grid.Row="4"
Grid.Column="1"
VerticalAlignment="Center"
Value="{Binding Path=NewTemporaryZone.IsEnable,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
x:Name="Cmb_AllowNonLBILogon"/>
In my model class I declare an IsEnable property:
private bool _isEnable;
public bool IsEnable
{
get { return _isEnable; }
set
{
_isEnable= value;
OnPropertyChanged("IsEnable");
}
}
What's going on with my usercontrol. I miss something ? Please help me. T.T
Please check whether you have any binding error in the output window of VS.
Try refreshing your binding in Cmb_Selection_SelectionChanged. Something like:
BindingExpression b = cmb.GetBindingExpression(MyNamespace.ValueProperty);
b.UpdateSource();
I've had the same problem; with boolean dependency properties! Try switching the bool to a INullable<bool> (bool?) and apply the appropriate type conversions. This worked for me. Don't know if this is a bug or if value types are handled somewhat different compared to reference types when creating dependency properties? Maybe someone else could verify that.

Categories