SilverLight: Call Child Control Event from base file - silverlight

1) BaseFile
File Contains KeyDown Event that called when any key press.
private void MODULE_KeyDown(object sender, KeyEventArgs e)
{
//Here Need to Check Key press is (CTRL + ALT + S)
if (Keyboard.Modifiers == (ModifierKeys.Alt | ModifierKeys.Control) && e.Key == Key.S)
{
var objMBox = new ITSUI.MBox("Do you want to save records?", "Confirm", MBoxButtons.YesNo);
objMBox.Closed += delegate
{
if (objMBox.m_Return == MBoxReturn.Yes)
{
**Here Need to call Detail Child Control OnOk Event**
}
};
objMBox.Show();
}
}
2) Detail Child Control
public void OnOk(object sender, RoutedEventArgs e)
{
//Save Record Code Here
}
How to call OnOk Event of Child Control from Base File?

If you need to call a child control's method from your code-behind you can set a name to the control in your view and just use its name.
<UserControl class="MyView">
...
<MyChildControl x:Name="RecordEditView"/>
...
</UserControl>
and in your code-behind:
public class MyView : UserControl {
public MyView()
{
InitializeComponent();
this.KeyDown += OnMyViewKeyDown;
}
private void OnMyViewKeyDown(object sender, KeyEventArgs e)
{
RecordEditView.SaveRecordData();
}
}
public class MyChildControl : UserControl
{
public void SaveRecordData()
{
...
}
}

Related

Programatically change state of GridViewCheckBoxColumn row with updating binding source for Telerik's GridView

I'm making a custom behavior for Telerik's RadGridView.
When this behavior is attached and its PropertyName is set to same property as specified by
DataMemberBinding value of some of the GridViewCheckBoxColumn of the grid, then toggling the checkbox in that column will apply same checkbox state to all selected rows (but only to the same column).
That happens in the ApplyToAllSelected method, namely in gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked); line. The visuals are working as expected, and all checkbox values are updated on screen.
The Problem is that the binding source is not updated for those rows. Only for the one where click happened. GridViewCheckBox.IsChecked dependency property does not seem to be bound directly to the datacontext's property, so gvcb.GetBindingExpression(GridViewCheckBox.IsChecked) returns null.
The Question: how to update source after setting checkbox state?
public sealed class CheckAllSelectedBehavior : Behavior<RadGridView>
{
public event EventHandler Toggled;
public string PropertyName { get; set; }
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.PreparingCellForEdit += this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded += this.AssociatedObject_CellEditEnded;
}
protected override void OnDetaching()
{
this.AssociatedObject.PreparingCellForEdit -= this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded -= this.AssociatedObject_CellEditEnded;
base.OnDetaching();
}
private void AssociatedObject_CellEditEnded(object sender, GridViewCellEditEndedEventArgs e)
{
if (e.Cell.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked -= this.Cb_Checked;
cb.Unchecked -= this.Cb_Unchecked;
}
}
private void AssociatedObject_PreparedCellForEdit(object sender, GridViewPreparingCellForEditEventArgs e)
{
if (e.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked += this.Cb_Checked;
cb.Unchecked += this.Cb_Unchecked;
}
}
private void Cb_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(false);
}
private void Cb_Checked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(true);
}
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
var row = this.AssociatedObject.GetRowForItem(item);
var cell = row.GetCellFromPropertyName(this.PropertyName);
if (cell.Content is GridViewCheckBox gvcb)
{
gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked);
}
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
}
Using reflection to set the value on viewmodel property seems to work. Modify the ApplyToAllSelected method like follows:
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
this.SetProperty(item, isChecked);
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
private void SetProperty(object target, bool isChecked)
{
var prop = target.GetType().GetProperty(
this.PropertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
prop.SetValue(target, isChecked);
}

Defining eventhandlers outside MainWindow?

I am trying to define some event handlers inside auser class but im not sure how. The MainWindow needs the handler definitions.
public abstract partial class MainWindow: Window {
public User user = new User();
}
public class User {
internal void ExampleMouseEventDown(object sender, MouseEventArgs e) {
// Does stuff;
}
}
Isnt there a way to somehow make this work? Such as:
mainWindow.AddHandleDefinition += ExampleMouseEventDown();
Also tried this:
public partial class MainWindow : Window {
public MainWindow() {
User user = new User(this);
}
}
public class User
{
internal User(MainWindow w)
{
w.AddObserverButton.MouseUp += ExampleMouseEventDown;
}
internal void ExampleMouseEventDown(object sender, MouseEventArgs e)
{
// Does stuff;
}
}

User control and event for Padding changed

Im working on gauge control.
I need to redraw everything inside when Size or Padding property is changed.
This is how I deal with Size property changes:
public RoundGauge()
{
this.SizeChanged += delegate
{
ReDrawEverything();
};
InitializeComponent();
}
But there is no PaddingChanged event. What can I do with this?
There is no indeed no "PaddingChanged" event but you could use a DependencyPropertyDescriptor to subscribe to changes to a dependency property:
public partial class RoundGauge : UserControl
{
public RoundGauge()
{
InitializeComponent();
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(PaddingProperty, typeof(UserControl));
if (dpd != null)
dpd.AddValueChanged(this, OnPaddingChanged);
}
private void OnPaddingChanged(object sender, EventArgs e)
{
MessageBox.Show("Padding changed!");
}
}
Please refer to the following blog post for more information.
Handling changes to dependency properties in the view: https://blog.magnusmontin.net/2014/03/31/handling-changes-to-dependency-properties/
You can override OnPropertyChanged event:
public partial class RoundGauge : Control
{
public RoundGauge()
{
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if (e.Property == PaddingProperty)
{
Thickness oldPadding = (Thickness)e.OldValue;
Thickness newPadding = (Thickness)e.NewValue;
// ...
}
}
}

How to create user define (new) event for user control in WPF ?one small example

I have one UserControl in which I am using a Canvas, and in that Canvas one Rectangle. I want to create a click event for that user control (Canvas and Rectangle) which I then want to use in the main window.
The question is: I want to create a new click event for the UserControl. How to do it? Kindly show little example or the code.
A brief example on how to expose an event from the UserControl that the main window can register:
In your UserControl:
1 . Add the following declaration:
public event EventHandler UserControlClicked;
2 . In your UserControl_Clicked event raise the event like this:
private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
{
if (UserControlClicked != null)
{
UserControlClicked(this, EventArgs.Empty);
}
}
In your MainWindow:
Your usercontrol will now have a UserControlClicked event which you can register to:
<local:UserControl1 x:Name="UC" UserControlClicked="UC_OnUserControlClicked" />
i find this easier for passing value to handler:
public event Action<string> onUserCodeFetched;
private void btnEnterClicked(object sender, RoutedEventArgs e)
{
onUserCodeFetched(PersonellCode.Text);
PersonellCode.Text = "";
}
It's an old question, but I also found useful to bypass the event using a property-like custom event as in here. You can use a general EventHandler or you can be more specific (RoutedEventHandler, MouseButtonEventHandler, etc) to avoid later casts. For instance, to bypass a click event, you could write in your custom control class:
public readonly object objectLock = new object();
public event RoutedEventHandler CustomClick
{
add{ lock (objectLock) { myClickableInnerControl.Click += value;}}
remove {lock (objectLock) { myClickableInnerControl.Click -= value; }}
}
and for a PreviewMouseDown event, it would be something like:
public readonly object objectLock = new object();
public event MouseButtonEventHandler CustomPreviewMouseDown
{
add{ lock (objectLock) { myInnerControl.PreviewMouseDown += value;}}
remove {lock (objectLock) { myInnerControl.PreviewMouseDown -= value; }}
}
Where myInnerControl would be your canvas in this case.
Then you can initialize the event from xaml as
<local:myClickableControl x:Name="ClickCtrl1" CustomClick="ClickCtrl1_CustomClick" />
or
<local:myCustomControl x:Name="CustomCtrl1" CustomPreviewMouseDown="CustomCtrl1_CustomPreviewMouseDown" />
And from code behind:
ClickCtrl1.CustomClick+=ClickCtrl1_CustomClick;
or
CustomCtrl1.CustomPreviewMouseDown+=CustomCtrl1_CustomPreviewMouseDown;
You can also subscribe your callback to several inner controls events (being careful when they overlap as some events like previewMouseDown are not only fired by the front control but also by the controls underneath).
public readonly object objectLock = new object();
public event MouseButtonEventHandler CustomPreviewMouseDown
{
add{ lock (objectLock)
{
myInnerControl1.PreviewMouseDown += value;
myInnerControl2.PreviewMouseDown += value;
}}
remove {lock (objectLock)
{
myInnerControl1.PreviewMouseDown -= value;
myInnerControl2.PreviewMouseDown -= value;
}}
}
(If the inner controls partially overlap, you can use the corresponding eventArgs Handled property in your callback method to avoid repetitions)
Finally, you can add a layer of control to the event fired by your inner control:
bool MousePreviewDownUsed = false;
event MouseButtonEventHandler _myPreviewMouseDownEvent = null;
public event MouseButtonEventHandler CustomPreviewMouseDown
{
add
{
lock (objectLock)
{
_myPreviewMouseDownEvent += value;
if (value != null && !MousePreviewDownUsed)
{
myInnerControl.PreviewMouseDown += myInnerControl_PreviewMouseDown;
MousePreviewDownUsed = true;
}
}
}
remove
{
lock (objectLock)
{
if (_myPreviewMouseDownEvent != null)
{
_myPreviewMouseDownEvent -= value;
if ((_myPreviewMouseDownEvent == null ||
_myPreviewMouseDownEvent.GetInvocationList().Length == 0)
&& MousePreviewDownUsed)
{
_myPreviewMouseDownEvent = null;
myInnerControl.PreviewMouseDown -= myInnerControl_PreviewMouseDown;
MousePreviewDownUsed = false;
}
}
}
}
}
private void myInnerControl_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
// Do some previous operations or control whether the event must be broadcasted
_myPreviewMouseDownEvent?.Invoke(sender, e);
}
This event is initialized from xaml or code behind the same way as before.

TextBox AttachedProperty to Select All text not working as expected?

I have an attached property called "SelectAllOnFocus". Values of true/false.
public static class TextBoxProps
{
private static void MyTextBoxKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
((TextBox)sender).Text = string.Empty;
}
}
public static void SetSelectAllOnFocus(DependencyObject dependencyObject, bool selectAllOnFocus)
{
if (!ReferenceEquals(null, dependencyObject))
{
dependencyObject.SetValue(SelectAllOnFocus, selectAllOnFocus);
}
}
public static bool GetSelectAllOnFocus(DependencyObject dependencyObject)
{
if (!ReferenceEquals(null, dependencyObject))
{
return (bool)dependencyObject.GetValue(SelectAllOnFocus);
}
else
{
return false;
}
}
private static void OnSelectAllOnFocus(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool selectAllOnFocus = (bool)e.NewValue == true;
var theTextBox = d as TextBox;
if (selectAllOnFocus && theTextBox != null)
{
theTextBox.PreviewMouseDown -= MyTextBoxMouseEnter; theTextBox.PreviewMouseDown += MyTextBoxMouseEnter;
}
}
private static void MyTextBoxMouseEnter(object sender, MouseEventArgs e)
{
((TextBox)sender).SelectAll();
e.Handled = false;
}
public static readonly DependencyProperty SelectAllOnFocus
= DependencyProperty.RegisterAttached("SelectAllOnFocus", typeof(bool), typeof(TextBoxEscapeProperty),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnSelectAllOnFocus)));
}
What happens is the following:
The PreviewMouseDown event gets triggered.
The MyTextBoxMouseEnter method gets called.
The SelectAll() Method gets called.
When I do a "watch" on ((TextBox)sender).SelectedText, the value is correct (meaning whatever is in the textbox is showing up as selectedText).
The textbox itself is unchanged. No text is selected.
This is part of a general WPF style. All textboxes in the application should receive this property and it's associated behavior.
I'm stumped. Any ideas?
Thanks
What happens if you call ((TextBox)sender).UpdateLayout(); immediately after the SelectAll command? Or maybe you need to set the Keyboard focus to the text box.
It might be a better option to use something like this, which works if the text box is being selected with the mouse or the keyboard. (You'll need to modify it to check your "SelectAllOnFocus" property)
In your App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
// Select the text in a TextBox when it receives focus.
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent, new RoutedEventHandler(SelectAllText));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent, new RoutedEventHandler(SelectAllText));
base.OnStartup(e);
}
void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}

Resources