Update Source Without Losing Focus - WPF Telerik RADDatePicker - wpf

I have a Telerik RadDatePicker, which I am binding to the SelectedDate property. I want this control to show a validation error when the default date set in the control is removed/deleted. I was able to achieve this, but the problem was that the validation error occurs only when Enter is pressed or when we click outside the control.
Is there a way tell RadDatePicker to update the source without moving the focus? (Tried UpdateSourceTrigger=PropertyChanged, but still it wasnt working)

You can use a Behavior that catches whatever (keystrokes, value changes, etc.) and force databinding update.
I have written a similar one to use in Silverlight's TextBox, since in Silverlight you can't change the UpdateSourceTrigger like in WPF.
You can use the following code and make the required adjustments:
public class TextBoxUpdateBehavior : Behavior<TextBox>
{
public TextBoxUpdateBehavior()
{
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
}
private void AssociatedObjectOnTextChanged(object sender, TextChangedEventArgs args)
{
var bindingExpr = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
bindingExpr.UpdateSource();
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
}
}

I might be a bit late now, but you can use CurrentDateTimeText property of RadDatePicker

To extend zish's answer, I use the RadDatePicker's SelectedDate property bound to my VM's DateTime? SelectedDate property with no validation set in the binding. I use the RadDatePicker's CurrentDateTimeText property bound to my VM's string SelectedDateText property with ValidatesOnErrors=True in the binding. Then, in the VM, I validate that !String.IsNullOrEmpty(SelectedDateText). This gives me the behavior that I want without the need for a behavior.

Related

Why is there no IsReadOnlyChanged event on TextBox controls?

I was adding some workaround code to fix the bug outlined in Is this a bug in DotNet 4 WPF Spell Checking?, (When a WPF TextBox changes Enabled, Visible or ReadOnly states, any SpellCheck custom dictionaries get dropped off until you disable and re-enable SpellCheck) and the simplest fix seemed to be to handle the IsVisibleChanged, IsEnabledChanged, and IsReadOnlyChanged events.
Simple, right? Except there is no IsReadOnlyChanged event. Anybody know why and what the best way to trap a change to IsReadOnly in a WPF TextBox would be?
You can always follow dependency property change with DependencyPropertyDescriptor.AddValueChanged
DependencyPropertyDescriptor.FromProperty(TextBoxBase.IsReadOnlyProperty)
.AddValueChanged(ctrl, OnReadOnlyChanged)
Create a custom class and handle OnPropertyChanged event. Sth like this:
public class MyTextBox: TextBox
{
public MyTextBox() { }
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property.ToString() == "IsReadOnly")
{
// here you are sure that ContentPropertyhas changed
}
}
}

Override default value of TextBox.TextProperty

I have a custom control that derives from TextBox. And I cannot find a way to override the default Text value. So, in short - I want MyTextBox to have some specific default text in it.
The code:
public class MyTextBox : TextBox
{
static MyTextBox()
{
TextBox.TextProperty.OverrideMetadata(
typeof(MyTextBox),
new FrameworkPropertyMetadata("DEFAULT TEXT", OnTextChanged));
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
The problem is that the property (strangely) contains the "DEFAULT TEXT" value, yet it does not show up in the UI (text box is empty).
What am I doing wrong?
The TextBox uses an inner class to provide most of it's functionality. This same class is shared with RichTextBox. I believe the TextBox assumes Text will be empty when constructed, so the UI is not updated.
One thing to keep in mind is that you have effectively short-circuited the TextBox.OnTextPropertyChanged method from being called. If you want to override the PropertyChangedCallback, then you'd probably need to manually call the TextBox version to ensure everything works as expected.
You can get to the base class's PropertyChangedCallback using TextProperty.GetMetadata(typeof(TextBox)).PropertyChangedCallback.
You may be able to call the TextBox's PropertyChangedCallback in an instance constructor to force the UI to update. Otherwise, you'd need to set Text directly.

wpf converter : setting multiple properties

I am used to using converters that return a value per property, such as Foreground color.
Is it possible to have a converter that works with multiple properties?
such as: Foreground, Background, Font-Weight, Font-Size
How can I create one converter (or less than 4) that could set multiple properties?
No, converters aren't designed for that. You could possibly go down the attached behaviour route and set the properties, based on a bound dependency property (I assume) on attach?
Edit: behaviours are part of the Blend SDK, the basic structure of what you want is:
public class MyBehavior : Behavior<TextBlock>
{
//// <-- Dependency property here
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Foreground = CalculateForeground();
this.AssociatedObject.Background = CalculateBackground();
// etc..
}
private Brush CalculateForeground()
{
// Do some calculations based on the dependency property
}
private Brush CalculateBackground()
{
// Do some calculations based on the dependency property
}
protected override void OnDetaching()
{
base.OnDetaching();
// You might want to reset to default here, or just do nothing
}
}

Custom Mark-up Extensions return RoutedEvents

I'm trying to create a generalized event for my Close buttons, where they have to close the window but before that set focus to the owner window. I don't want to have an event for every file for that, because that'd be pretty unpractical since I have 30+ windows in my application. (So if I wanted to change that behavior, i'd have to change on 30 files everytime)
I'm not sure if that's the correct approach, but I tried making a MarkUp Extension which returns a delegate(object sender, RoutedEventArgs e) Here is the code:
delegate void RoutedDelegate(object sender, RoutedEventArgs e);
[MarkupExtensionReturnType(typeof(RoutedEvent))]
public class CloseWindowExtension : MarkupExtension
{
Window win = null;
public Window Win
{
get { return this.win; }
set { this.win = value; }
}
public CloseWindowExtension(Window win)
: base()
{
this.win = win;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (win == null)
{
throw new InvalidOperationException("The window must be specified!");
}
return new RoutedDelegate(delegate(object sender, RoutedEventArgs e)
{
Extensions.FocusClose(win);
});
}
}
The FocusClose method gets a window, closes it, but sets focus to its owner before. But I can't make it work. When i set my button in the xaml,
Button Click="{e:CloseWindow {Binding win}}"
(win is my Window name), I get the error message:
Click="{e:CloseWindow {Binding win}}" is not valid. '{e:CloseWindow {Binding win}}' is not a valid event handler method name. Only instance methods on the generated or code-behind class are valid. Line 28 Position 17.
Am I doing something wrong? Is this the best approach or do I have another options?
Thanks in advance!
Clark
You can't use a markup extension to set an event handler. Instead, you can use an attached behavior, which allows you to bind a command to an event.
See this article by Marlon Grech for details
.NET 4.5+ supports markup extensions for events, so you can implement what you wanted now :)

WPF User Control's DataContext is Null

I have a user control where the XAML of the control can bind to the appropriate properties from the parent's data context like normal (the data context propagates in xaml).
For example, I have a window whose DataContext I am setting to ObjectA for example. My user control within the window is then try to access the properties within the dataContext
So my window's xaml and code behind can both see a non-null DataContext.
My control that DataContext propagates to can see a non-null DataContext in the Xaml but not in the code behind.
What is the proper way of handling this?
failing that if you need to check whether the DataContext is being set you can use the DataContextChanged
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
DataContextChanged += new DependencyPropertyChangedEventHandler(UserControl1_DataContextChanged);
}
void UserControl1_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// You can also validate the data going into the DataContext using the event args
}
}
Note it wont enter UserControl1_DataContextChanged until DataContext is changed from null to a different value.
Not sure if this answers your question but can be quite handy to use in debugging issues.
I think you are checking the 'DataContext' in the constructor of the UserControl. It will be null at the Constructor since the user control hasnt yet created while execution is in the constructor code. But check the property at Loaded event you will see the object properly.
public partial class UserControl1
{
public UserControl1()
{
this.InitializeComponent();
//DataContext will be null here
this.Loaded += new RoutedEventHandler(UserControl1_Loaded);
}
void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
//Check DataContext Property here - Value is not null
}
}
I would check to see whether you are having a binding error at runtime. Add this namespace to your XAML:
xmlns:debug="clr-namespace:System.Diagnostics;assembly=System"
and check the debugger's Output window for relevant error messages.
Alternatively, can you show us more code?

Resources