I am trying to create a simple onscreen keypad created using buttons (currently a User-control), on those buttons i have a click event, when i click/touch a button i want the value of that button sent to a Text-block in my Main-window.
I can't/don't understand how to make the User-control (keypad) see the Text-block (in Main-window) to add in the value that i need.
I have seen solutions that use command Bindings and solutions that use the visual tree traversing but all of them are the main window accessing the user control, not the other way around.
All the examples are the other way around because that is how a UserControl is supposed to work.
A UserControl is a packaged piece of re-usable functionality. It should not know anything about the code that is using it.
Instead you should expose routed events in your UserControl for things like a when number was selected, and subscribe to them in your main window.
There are many ways to achieve what you want. If your MainWindow.xaml has a UserControl and you want to react to a change from the control in the MainWindow.xaml.cs file, then you could add a delegate to the UserControl code behind and register a handler for it in the MainWindow.xaml.cs file. Implementing new delegates are generally somewhat simpler than implementing RoutedEvents, which is another way that you could handle this situation.
Using a delegate like this will enable you to effectively pass a signal to the main view from the child UserControl code behind, which you can react to in any way you want to. Rather than explain the whole story again here, please see my answers from the Passing parameters between viewmodels and How to call functions in a main view model from other view models? posts here on Stack Overflow for full details on how to achieve this.
Related
I have a UWP question about inheriting/ passing a event to a user control from the parent view to child.
I created a user control to display text overlays (see code below). We had a parent view that would display an overlay when the window is resized (see code below). The overlay would display the dimensions of the window when this even is triggered.
I moved the overlay to a user control and now I'm trying to pass that resized event to the overlay control. The hope is that we can register more events to the overlay control so it can display more then the resize
information. However, I'm not sure the best way to do this. My first idea was inheriting from the view, so i could just listen to the event from the overlay control, but that resulted in errors.
I believe due to the fact that the parent view has a ViewModel (i also created one for the overlay, not sure if its actually needed yet).
I have been reading about a lot of possible ways to do this, but I'm not sure which would be the best way to do this. Does anyone have any insight on this issue ? I would be open to suggestions, links, or just a general answer of
what is the best way to achieve this in our project.
Parent view
User Control
Parent Event
Control class
Some information i have been reading about:
https://documentation.devexpress.com/WPF/17449/MVVM-Framework/ViewModels/ViewModel-relationships-ISupportParentViewModel
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/preview-events
https://social.msdn.microsoft.com/Forums/windows/en-US/742077f6-e875-44d1-8bc4-6e6516db9eda/passing-the-parent-control-event-to-child-controls?forum=winforms
https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/events-and-routed-events-overview
http://irisclasson.com/2013/12/10/passing-event-arguments-from-xaml-in-windows-store-apps-inputconverter-inputconverterparameter-etc/
https://learn.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service
Update
Adding the viewModel to the parent viewModel (terminal), and passing it to the control via the Datacontext did not work
As you're already using MVVM, I'd recommend going the full route utilizing "Interactivity", "Commands", and "child ViewModels". This is a commonly used patter in MVVM WPF applications, and can be applied to UWP apps as well.
Using "Interactivity" and interactions
The interactivity / behaviors library from Microsoft allows you to bind events in XAML to an ICommand in the ViewModel. You can get the managed NuGet package here.
From the official examples on GitHub, shortened:
<Button x:Name="button1" Content="Increment">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="Click" SourceObject="{Binding ElementName=button1}">
<Interactions:InvokeCommandAction Command="{Binding UpdateCountCommand}"/>
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
Forward command data to child ViewModel
Having this event now routed to your command in your parent ViewModel, you can now either call your overlay ViewModel and pass the info directly to it:
private readony IOverlayViewModel _overlayViewModel;
public ICommand UpdateCountCommand { get; set; }
ctor(IOverlayViewModel overlayViewModel)
{
_overlayViewModel = overlayViewModel;
UpdatedCountCommand = new MyICommandImplementation(UpdatedCountCommand_Executed);
}
private void UpdatedCountCommand_Executed(/* Add correct method signature */)
{
// If needed, retrieve data from parameter...
// Update overlay ViewModel text
_overlayViewModel.Text = ""; // Whichever text was calculated before
}
Or you use a messenger (mediator pattern) to send it to an overlay.
I was misusing the bindings. x:Bind and Binding are using different types of context. For this binding to work we would need to set the parent's element Datacontext to 'this'. x:Bind on the other hand does this implicitly.
<views:OverlayView DataContext="{x:Bind ViewModel.Overlay}"></views:OverlayView>
I am using MVVM in my project and I am implementing the Diagram Designer and I am using RAD Diagram control of Telerik.I am dragging the shape from my RadToolBox to canvas for which I have implemented the event.Now on this event I want to save the diagram in RavenDB once the shape has been dropped on Canvas ( Ruler).This whole thing is in the User control stored in one library and I am creating the reference of this library in my actual WPF form which is in other library.My requirement is I want to call the Save command which is present in View Model of WPF form, from my xaml.cs of the user control and this user control is present in other library.
How shall i achieve the same.Please help.
Why do have multiple assemblies? If you don't need them, then make your life simpler and just use NameSpaces to separate your controls from your forms in the same assembly.
Right now that's said :-)
The easy way is via an Event. Add an event to your UserControl, and then in the Window add the code when the event happens.
Have a read through MSDN Events
I really dont Why you would need to call a save command from another WindowsForm.
Telerik UI Diagram provides indefined save Command which is used to save the Diagram,
InXAML,
<Grid.CommandBindings>
<CommandBinding Command="telerik:DiagramCommands.Save" Executed="ExecuteSave" />
</Grid.CommandBindings>
And In code behind define save function,
private void ExecuteSave(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
this.diagram.save();
}
I'm currently very stuck with this, my designer wants to have our app with WindowStyle.None to remove the borders and default ugly controls, he has then add custom controls, usually to allow dragging in the past we have used a rectangle and monitored the mousedown event to allow for dragmove.
However with Caliburn micro we lose control of the window because windowmanager create this for us, I'm aware you can override the create window method, but this still doesn't give access to adding UI elements to the window itself and binding to those events. Or at least i can work out a way to do this.
Basically what we are trying to achieve is the "mainwindow" with a WindowStyle.None and that ability to drag and move the window. My googling has failed to give a solid answer on this, and im hoping someone here has an idea.
Caliburn.Micro doesn't force you to make the all your views UserControls. The main view or the one your showing as the main window can be a Window control and you can set properties directly on that Window such as "WindowStyle.None". When Caliburn.Micro sees that the view behind your main view model (the view model you are using as the root, then one you are creating first) is actually a Window and not a UserControl then it will honor this and show that window, It Will Not create a new Window. So you can set your properties directly on that Window and everything shall work fine.
The Caliburn.Micro WindowManager provides overrides to its Show methods that allow you to set the settings of the window that is created.
Have a look here for an example.
Alternatively, you can use a Window directly as your view type (in XAML and the generated code behind file), and set the properties declaratively in the XAML.
If you wish to enable all of your dialogs etc to have common UI components, then you could create a derived WindowManager type that delegates the call to the CM WindowManager but wraps the passed in view model with your common view model. Then register this custom window manager in the bootstrapper rather than the default CM window manager.
So I followed the guide on the following site to restrict the characters a textbox can accept.
http://www.rhyous.com/2010/06/18/how-to-limit-or-prevent-characters-in-a-textbox-in-csharp/
My problem is I can't figure out how to make the event handler trigger in the secondary class. Basically how do I tell VS to look for the event handler code in that class instead of MainWindow? I tried searching, but apparently don't know the correct terms to use. The xaml reference I used was
xmlns:DigitBox="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
Any ideas?
Simplest way I've found to do it is assign the event in your constructor.
public MainWindow()
{
InitializeComponent();
TextBoxCurrency.GotFocus += expandedTextBoxEvents.TextBoxCurrencyGotFocus;
TextBoxCurrency.LostFocus += expandedTextBoxEvents.TextBoxCurrencyLostFocus;
}
I've searched a way to do it in XAML and I did not found an easy and clean way to do it.
You are much better off using commands and command bindings. I'm not sure what the specific command that would would bind to for a text box for your desired functionality, but one of the goals for WPF was to lessen the use of Event Handlers in code behind.
Check out this article for an overview of commands and this article for a way to hook up commands with events. WPF commanding is one of the coolest features to enable true separation of concerns between UI and business logic.
As a worst case scenario solution, you could create your own text box that inherits from the text box control and hook up the events in that class. Your control would then be reusable.
I'm designing a custom form in a WPF ResourceDictionary using a controltemplate so I can easily use the window later on. I'm designing it with Expression Blend and I'm stuck on getting the close, maximize and minimize buttons to work.
At first I wasn't able to access any of the events, however this stackoverflow question helped me with binding a class to the resourcedictionary. When I try to access the click event for the close, min and max buttons, I get in the code editor and the btn_Close eventhandler shows up.
When I try to compile it gives me the error "application.Resources doesn't contain a defition for close (...)" (Resources is the name of the class)
(when I type "this." intellisense gives me many commands but not .Close)
I'm pretty sure all of the namespaces in both the class and XAML are right, how do I get this working properly? Or do I need to code this seperately for each form that uses this template?
In the strange situation you've arranged, this in the code-behind does not refer to a Window but to the ResourceDictionary. Nevertheless, the event when it occurs will be generated by a window so instead of using this you need to cast the sender parameter to a Window and Close that instead.