Focus control from ViewModel - c#

Why is the 1st button "active" when I am not hovering over the button or anything. This seems to happen after I change tabs.
I suspect that when I change tabs, it focuses the 1st control. Is that the case? I am developing a MVVM app, so from my view model, how might I focus the text box instead?

Since WPFs concept of focus is kinda complicated, I have a class called FocusEnforcer.
It really really makes sure the desired control gets the focus, no matter what.
public static class FocusEnforcer
{
public static void EnforceFocus(UIElement element)
{
if (!element.Focus())
{
element.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new ThreadStart(delegate()
{
element.Focus();
}));
}
}
}

This kind of behavior requires just that: a behavior. Or, at least, a new attached property.
Create an attached property for tab controls.
Create a handler for changes to this attached property.
In this handler, subscribe to the TabControl's SelectionChanged event.
In the SelectionChanged event handler, use the TabControl.FindName method to get the text box.
Execute the FocusManager.SetFocusedElement method using the TabControl as the focus scope.

Related

VisibleChanged don't raise when not visible

I'm working on c# WinForm.
I have an custom UserControl : MyControl : UserControl, INotifyPropertyChanged. I attached a method on event on event VisibleChanged : this.VisibleChanged += new System.EventHandler(this.MyControl_VisibleChanged);
My application have some pages, each page is a control like MyControl. Top of MainWindows contains Button, used to switch tab.
My problem is that my function MyControl_VisibleChanged is called only when Visible is changing to true. I added a test in a tab to check MyControl.Visible, when I select the other tab, MyControl.Visible is false but no event is raised.
I've try to define a new property Visible for this control but value is never set, only the base value is modify.
Can you help me to find a solution ?
This is a quirk in the way Visible works, explained here. His solution was to use properties that he has complete control over, but you could instead have a method allowing the tab switches to tell their children to raise their VisibleChanged event that extra time.
The first two answers to this question may also be useful.

Raise event in a User Control to MainWindow

Sorry first, because I see another question, but both of the ans. and ques. is not clear enough
How can I raise a parent event from a user control in WPF?
In my MainWindow.xaml, I had a right Panel
<local:RightSideContent x:Name="RightPanel" Grid.Column="1">
So in the MainWindow.xaml.cs, if I want rise an event to this panel, I made the code like this:
public delegate void Event1();
public MainWindow()
{
this.InitializeComponent();
Event1 obj = new Event1(this.RightPanel.func);
obj();
// Insert code required on object creation below this point.
}
And in RightPanel class, I declare the function func
The question is: if I am in the RightPanel Class, how I raise an event to the MainWindow, because I can't wrote something like this.RightPanel.func.....
And by the way I am in another class that do not have xaml file, if I want raise an event to a UserControl, how can I do?
Sorry, I don't quite have enough rep to post a comment to clarify, but as I see it, there are three possible things you are trying to do here.
You are trying to trigger an event on MainWindow, from some code that doesn't reside in MainWindow. In which case, you need to make sure that you have a reference to MainWindow, and that there is a public method on MainWindow that will trigger that event.
You want MainWindow to handle a click etc that comes from RightPanel. In that case you simply put a Button.Click="blah" (or whatever the event is) attribute on your MainWindow, and it will catch any button clicks from below it that are not handled lower down. In fact you can even handle it lower down and make sure that you set the EventArgs so that it is effectively unhandled, so that you can then handle it higher up as well.
You want to be able to handle a custom event generated in RightPanel, in a similar way to the way you would the button click scenario from item 2 above. In this case, I would direct you to http://msdn.microsoft.com/en-us/library/ms742806.aspx which is the documentation for Routed Events in WPF, and you should be able to work out how to create your own RoutedEvent from there.

wpf custom control events

I want to create a custom wpf control that contains a Button and a ContentPresenter. As WPF controls are supposed to be lookless I created a class that is supposed to contain my control's behaviour and I put default style for the control inside generic.xaml file. So far so good.
But how do I make my button raise an event (routed event?) and handle it in my control's class? I figured out that I can add code behind file for the ResourceDictionary from generic.xaml and put my event handlers there, but that would associate behaviour of my control with its template and is therefore not desirable. Another idea I have seen (but not yet tried) is to use TemplatePart mechanism to locate some key controls inside the template and subscribe to events in code. But that does not seem flexible enough for me because it may happen that the user of my control will want to replace button with a control that does not have any event I know of at the time of designing my control.
So how do I raise event in XAML when button is clicked and subscribe to it in my control's code file?
Override the OnApplyTemplate method of the control.
That is where you know the template has been applied and you can use GetTemplateChild to get a reference to a control.
E.g.:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var myButton = this.GetTemplateChild("myButton") as Button;
if(myButton != null)
{
myButton.Click += ...;
}

Loaded event of a WPF user control fires more than once

To implement a tab-based environment in WPF we need to convert our forms to user controls, however when doing this, the Loaded event of the user control is called two times.
While searching on the internet other people also pointed this issue. How can we ensure that loaded event is called only once? Because when it is called multiple times, initialization of our controls happens multiple times.
As explained in this blog, the Loaded event is fired when ever a control is about to be rendered (i.e. added to the visual tree).
There are several controls that would cause your control to be loaded/unloaded multiple times. For example, the native WPF TabControl only renders the content of the selected tab. So when you select a new tab, the content of the previously selected tab is unloaded. If you click back to the previously selected tab, then it's content is reloaded.
One work around is to use a Boolean to flag whether you have already initialized your control, as suggested by others. Alternatively, you may be able to use the Initialized event instead.
Your routed event handler can (and should) remove itself from the Loaded hook as the first thing it does.
public class MyClass : Window
{
public MyClass()
{
Loaded += MyLoadedRoutedEventHandler;
}
void MyLoadedRoutedEventHandler(Object sender, RoutedEventArgs e)
{
Loaded -= MyLoadedRoutedEventHandler;
/// ...
}
};
Set a loaded flag in the event, and, if the flag has already been set, don't do anything.
As mentioned above,you can use bool flag for it.
bool isPageLoadingForFirstTime = true;
public void LoadedEvent()
{
if(ispageLoadingForFirstTime)
{
//do something
ispageLoadingForFirstTime = false;
}
}

Handling the "X" close button in WPF under MVVM

I'm creating a basic database application in WPF, and I have started using the MVVM pattern.
I have a dialog that asks the user to select an item from a ListBox and click "OK." After that, I take the item the user clicked from a property in the view model and pass it into another dialog. But if the user clicks "Cancel," I set that value to null, and the action is canceled: I don't open the next dialog and return to the main screen. Example:
public class SelectEquipmentViewModel : WorkspaceViewModel
{
private bool _selected;
public Equipment SelectedEquipment
{
// Item selected by the user
}
// Action for "SelectCommand," which is attached to
// the "Select" button in the view
public void ExecuteSelect()
{
_selected = true;
// Fires a RequestClose event in WorkspaceViewModel,
// which is attached to the view's Close method
RequestClose();
}
public override void RequestClose()
{
if (!_selected)
{
// The user clicked "Cancel"
SelectedEquipment = null;
}
base.RequestClose();
}
}
This has been working great, but the problem comes if the user clicks the red "X" close button in the window's control box. The RequestClose method never gets invoked, and the selected item isn't set to null, which is bad.
I've considered attaching the view model to the Closing event of the view, but I feel this could get messy if I start creating handlers for all these events.
What would be the "preferred" way of handling this situation?
Thanks.
I think that using the EventToCommand behavior to wire up the Window object's Closing event to a new ExecuteCancel command is pretty clean.
public void ExecuteCancel()
{
_selected = false;
// Fires a RequestClose event in WorkspaceViewModel,
// which is attached to the view's Close method
RequestClose();
}
Where do you think this will get messy? If you add a Cancel button, it could use the same ExecuteCancel bits...
Behaviors are what you want to use to execute a command when the user presses the "X" button on window using MVVM. Check out Reed Copsey's blog here: http://reedcopsey.com/2009/10/09/using-behaviors-to-allow-the-viewmodel-to-manage-view-lifetime-in-m-v-vm/
You can download a sample application here...
I use this method all the time to allow the ViewModel manage the life of the view.
Approach without additional dependencies is described in article Handling a Window's Closed and Closing events in the View-Model and code with example provided. This does not add code behind xaml.
(Thanks to Reed Copsey's link)

Categories