If I have a user setting ToggleThis
I want to have this setting availabe to the user in a menu, say Settings/ToggleSettings. clicking it. Each click should toggle the user setting true/false but also update the menuItem icon to display the actual setting.
I can do this using
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Menu IsMainMenu="True">
<MenuItem Header="_Settings">
<MenuItem Header="_Toggle" Name="ToggleSettings" Click="MenuItem_Click">
<MenuItem.Icon>
<Image Source="Images/Toggle.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</Grid>
</Window>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
if (ToggleSettings.Icon == null)
{
Uri Icon = new Uri("pack://application:,,,/Images/" + "Toggle.png");
ToggleSettings.Icon = new Image
{
Source = new BitmapImage(Icon)
};
Properties.Settings.Default.toggleThis = true;
}
else
{
ToggleSettings.Icon = null;
Properties.Settings.Default.toggleThis = false;
}
}
}
}
However, I know this isn't the correct way of doing it as for example, on launch the menu probably won't be in the correct state based on previous settings. Trouble is, I don't know the right way. Can anyone give me some pointers on the right way to do this?
I'm assuming I need to use binding on both the icon and/or some value in the MenuItem but don't really know where to start.
Thank you
Actually there is no "right" way, there is only what works best, and what is most appropriate given the context.
Your example looks fine, it seems, so far at least, the only issue you have, is that you will not have the selected option in sync with what the user chose/didn't choose, the last time they used the software.
This requires only two small pieces of your code to be in two particular places.
Austin pointed out one of them already: Save your settings. This you should do right after your if/else in your method: MenuItem_Click. Just make sure the method does not exit somehow before the call to Settings.Save is made... a try/catch with a graceful way of ensuring a consistent settings state would be prudent.
The other is at the "time" you yourself mentioned: Initialization, or startup of the app. Somewhere in your app, before the initial loading is completed, you must access the setting you created (toggleThis) and use it to set the initial state of your menu item.
The best way to facilitate this, is to have a private method, which is responsible for both changing what icon is showing on the menu item, as well as storing the most recent state in the settings of the app. A method called Toggle() perhaps, which you call within your MenuItem_Click method. You need to give the menu item in question and ID though, that can be used to access the menu item in your code-behind though. As well, this code example assumes you have your icons stored in settings as well, although the icons can be coming from wherever, as long as you can reference them.
So your code could be something like this, although not exactly this:
public MainWindow()
{
InitializeComponent();
this.SetToggleIcon(Properties.Settings.Default.toggleThis);
}
private void Toggle()
{
this.StoreToggleState(!Properties.Settings.Default.toggleThis);
this.SetToggleIcon(Properties.Settings.Default.toggleThis);
}
private void SetToggleIcon(bool state)
{
this.menuItem_ToggleSettings.Icon = (Properties.Settings.Default.toggleThis) ? Properties.Settings.Default.IconTrue : Properties.Settings.Default.IconFalse;
}
private void StoreToggleState(bool state)
{
Properties.Settings.Default.toggleThis = state;
Properties.Settings.Default.Save();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
this.Toggle();
}
You need to call Save when you deem it appropriate.
Properties.Settings.Default.Save();
It's not entirely clear how you're using it but this will ensure the updated value is at least stored.
Related
Sorry if this has been asked before and I have spent about a week trying to find a similar question to point me in the right direction. I am teaching myself C# with WPF, XAML etc and am playing around with user controls. I made a simple app with a user control to load on top of other windows or user controls. The UC in question has two buttons and I need to get to the click events for each button in main window once the control is loaded. The main window has a button that loads the control.
Through some research I was able to find a solution from user SWilko (https://stackoverflow.com/a/28949666/10659981) but I can't figure it out for each button separately (click button a and show "clicked btn a", click button b and show "clicked button b"). I did try calling by sender using name and that will not work either. I feel like I am close with the help from the answer by SWilko but stuck.
Here is the code so far:
Basic main screen loading user control
<Window x:Class="UCBTN_TEST.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UCBTN_TEST"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="435">
<Grid>
<Button Content="Load Button" HorizontalAlignment="Left" Margin="18,23,0,0" VerticalAlignment="Top" Width="74" Click="Button_Click"/>
<Grid x:Name="GridLoad" HorizontalAlignment="Left" Height="300" Margin="120,23,0,0" VerticalAlignment="Top" Width="300" Background="#FFF1CBCB"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace UCBTN_TEST
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
GridLoad.Children.Clear();
GridLoad.Children.Add(new WindowControl());
}
}
}
The button user control
<UserControl x:Name="UCMain" x:Class="UCBTN_TEST.Controls.ButtonControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCBTN_TEST.Controls"
mc:Ignorable="d" d:DesignWidth="300" Height="40.333">
<Grid Background="#FFE7EEA7">
<Button x:Name="ButtonA" Content="Button A" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonA_Click" Background="Red"/>
<Button x:Name="ButtonB" Content="Button B" HorizontalAlignment="Left" Margin="215,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonA_Click" Background="Green"/>
</Grid>
</UserControl>
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace UCBTN_TEST.Controls
{
/// <summary>
/// Interaction logic for ButtonControl.xaml
/// </summary>
public partial class ButtonControl : UserControl
{
public ButtonControl()
{
InitializeComponent();
}
private void ButtonA_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(ClickEvent1, this));
}
public static readonly RoutedEvent ClickEvent1 = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ButtonControl));
public event RoutedEventHandler Click
{
add { AddHandler(ClickEvent1, value); }
remove { RemoveHandler(ClickEvent1, value); }
}
}
}
A second user control which would ultimately have some other controls once the buttons work correctly. But the button UC will load on top, simple button features related to WindowControl.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCBTN_TEST"
xmlns:Controls="clr-namespace:UCBTN_TEST.Controls" x:Class="UCBTN_TEST.WindowControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="#FFE7CFEE">
<Controls:ButtonControl HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="300" Click="Click1"/>
</Grid>
</UserControl>
I understand the behind code and why this is happening. My problem is that I need to have the buttons be unique in their events. I have tried calling by sender and name and that just kills the event all together.
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using UCBTN_TEST.Controls;
namespace UCBTN_TEST
{
/// <summary>
/// Interaction logic for WindowControl.xaml
/// </summary>
public partial class WindowControl : UserControl
{
public WindowControl()
{
InitializeComponent();
}
private void Click1(object sender, RoutedEventArgs e)
{
MessageBox.Show("This triggers both");
}
}
}
I was going to add a bunch of comments but really this is kind of answering the question and there's a lot to explain.
You should look into MVVM and mostly be thinking in terms of binding commands rather than which button was clicked. There are exceptions to this. For example, if you were building an on screen keyboard. The reason this is different because it's purpose can be encapsulated. The user presses a button which has "A" in it. Whatever textbox is focussed should be sent the character "A". They press a button showing "B" and similarly "B" should be sent. That functionality can be encapsulated in the control.
As it is, you have two buttons.
You put them in a usercontrol and encapsulate them.
By doing this you created a boundary.
This then creates a complication - which was clicked?
The usercontrol is also not particularly re-use friendly. If you add two then there are two buttonA and two button B. You could potentially improve that with a custom event args on your custom routed event and a dependency property on your usercontrol. Pass some usercontrol identifier along with which button was pressed.
This would be an unusual way to work though. I've rarely seen Custom routed events used in commercial apps.
All in all I would suggest the usercontrol mainly adds complexity.
Say you wanted to have 20 sets of 2 buttons.
Or 20 sets of 5 radiobuttons for a set of multiple choice questions.
The way to do that sort of thing is to use an itemscontrol and template out the multiple controls. One template giving 2 buttons ( or a textblock question and 5 radiobuttons for answers ) per row.
A click event is already a routed event and would bubble to the window. You may as well remove your custom routed event and the handler out the usercontrol... and the usercontrol. Just handle click in the window.
Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var btn = e.OriginalSource as Button;
if(btn == null)
{
return;
}
MessageBox.Show($"Button clicked was {btn.Tag}");
}
Markup:
ButtonBase.Click="Button_Click"
Title="MainWindow"
>
<Grid>
<StackPanel>
<Button x:Name="ButtonA" Content="Button A" Tag="A" Background="Red"/>
<Button x:Name="ButtonB" Content="Button B" Tag="B" Background="Green"/>
</StackPanel>
</Grid>
</Window>
I am fairly new to WPF and I am having a problem with inheriting from a user control.
I created a User Control and now I need to inherit from that control and add some more functionality.
Has anyone does this sort of thing before? Any help would be greatly appreciated.
Thank you
Well .. you create your base control
public abstract class BaseUserControl : UserControl{...}
then in the XAML file :
<Controls:BaseUserControl x:Class="Termo.Win.Controls.ChildControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Namespace.Of.Your.BaseControl">
And that should work.
EDIT: Hmm.. this example is useful when you have a base control without XAML and then inherit from it. The other way around(from a base control with Xaml) - I'm not sure how you can go about it.
EDIT2: Apparently from this post + comments i take that what you want might not be possible.
AFAIK you cannot inherit the xaml, you can only inherit the code behind.
We recently encountered the same problem on our project. The way we ended up solving our problem was to create a usercontrol and adding it to the "child" usercontrol.
If that doesnt work/help take a look at this:
https://web.archive.org/web/20200815091447/http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx[1]
I may have a bit of a solution: Composition instead of inheritance - I have come up with control, that has 'content slots' assignable from outside through databinding, look at my SO thread.
Example of use:
<UserControl ... >
<!-- My wrapping XAML -->
<Common:DialogControl>
<Common:DialogControl.Heading>
<!-- Slot for a string -->
</Common:DialogControl.Heading>
<Common:DialogControl.Control>
<!-- Concrete dialog's content goes here -->
</Common:DialogControl.Control>
<Common:DialogControl.Buttons>
<!-- Concrete dialog's buttons go here -->
</Common:DialogControl.Buttons>
</Common:DialogControl>
<!-- /My wrapping XAML -->
</UserControl>
Together with some handling code in codebehind it would be a nice base component for dialog windows.
You cannot inherit the xaml code it self. However creating an abstract class of the codebehind, will allow you to edit in code behind, from a derived class object.
Xaml Code: { Window1.xaml }
<Window
x:Class="WPFSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="auto" Width="256" Title="WPF Sameples">
<Grid>
<Button x:Name="Button1" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Click Me"/>
</Grid>
</Window>
CodeBehind: { Window1.xaml.cs }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPFSamples
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public abstract partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
Derived Class : { DisabledButtonWindow.cs }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WPFSamples
{
public sealed class DisabledButtonWindow : Window1
{
public DisabledButtonWindow()
{
Button1.IsEnabled = false;
}
}
}
although you cannot inherit from the wpf source it self, you are able to use this "Window1" control as a template for all other derived controls.
You can accomplish this by using a delegate.
Essentially, you need to create an interface (YourInterface) which wraps up the functionality you want, then make both the user control and your class implement that interface.
Next, make sure the user control has a reference to an object of type IYourInterface, so that when your user control attempts to invoke a method of the Interface, it calls your class' method.
Because both the user control and class implement the same interface, they can be seen as the same kind of object - meaning you can put them both into a collection of objects of type IYourInterface. This should give you the behavior you want.
In ASP.NET I use this technique often, by having my classes inherit from abstract class ancestors. I don't understand why WPF doesn't support this. :(
I think that you can do this but that you will have to redefine any functions and possibly some other stuff that you reference in the xaml in the child class.
IE if you have a button click event that you subscribe to in the base class xaml you will need override the button click in the child class and call the base class button click event.
Not one hundred percent sure of the the details since it's my coworkers code that I'm drawing from but thought this would give a start to anyone looking to implement this in the future.
I am very new to C# and I'm trying to initialize a XAML user control window when I start my scripting program. It's just a basic window with textboxes, and comboboxes. The XAML code and C# code are listed below respectively. Since I have Express, I am unable to use the MVVM light toolkit. I am also using VS2010 because that is what the original code for this program was. The VMS.TPS.Common.Model.API and Types are dll's used for this particular program. Keep in mind that the C# code has to have this basic skeleton, otherwise it won't work. The 'public void Execute' portion is where I need to code.
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="426" d:DesignWidth="736">
<Grid Margin="10" Width="702" HorizontalAlignment="Center">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VMS.TPS.Common.Model.API;
using VMS.TPS.Common.Model.Types;
using System.Windows;
using System.Windows.Forms;
using WpfApplication1;
namespace VMS.TPS
{
public class Script
{
public Script()
{
}
public void Execute(ScriptContext context, System.Windows.Window window)
{
}
}
}
It should be very simple if i understood it right :
UserControl1 testUsrCtrl = new UserControl1();
And then set required properties.
Make sure you have all the references in place.
I've been working with WPF for a little while now and I've had trouble forcing only one instance of a window to open from my MainWindow. I've been trying to find out if the solution I chose is the best one but there does not seem to be a lot in the way of this subject. Makes me wonder if I am going about it entirely the wrong way.
The original problem I was trying to solve was only allow one instance of a window to open, which I accomplished using a singleton model. It ended up working just fine, but I have two windows I want to open that I'd like this functionality on. I figured it would be nice to make a "BaseWindow" to inherit from, so I'd only need to implement this once. That's where I got stuck.
I've created a very simple project where I am trying to implement this idea, but instead I am getting hit with a protectional level error on the AboutWindow's public contructor, because the WindowBase contructor is private. Changing it to public allows the program to compile, but it seems to "skip" the AboutWindow contructor which has "InitializeComponent".
However as a side note, the portion that allows only one instance is indeed working. If I can get constructor with IniliatizeCompotent to work I'll be set. To clarify, any windows that derive from WindowBase can be open at the same time. So in this case, one OptionWindow at a time and one AboutWindow.
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="181" Width="259">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File"></MenuItem>
<MenuItem Header="_Tools">
<MenuItem Header="_Options" ></MenuItem>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About" Click="AboutMenuItem_Click"></MenuItem>
</MenuItem>
</Menu>
<Grid>
<TextBlock Text="Content would go here"></TextBlock>
</Grid>
</DockPanel>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace WpfApplication1 {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void AboutMenuItem_Click(object sender, RoutedEventArgs e) {
AboutWindow.Instance.Show();
}
}
}
AboutWindow.xaml:
<src:WindowBase x:Class="WpfApplication1.AboutWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WpfApplication1"
Title="AboutWindow" Height="300" Width="300">
<Grid>
<Label Content="Label" HorizontalAlignment="Left" Margin="84,74,0,0" VerticalAlignment="Top"/>
</Grid>
</src:WindowBase>
AboutWindow.xaml.cs:
namespace WpfApplication1 {
/// <summary>
/// Interaction logic for AboutWindow.xaml
/// </summary>
public partial class AboutWindow : WindowBase {
public AboutWindow() {
InitializeComponent();
}
}
}
WindowBase.cs:
using System;
using System.Windows;
namespace WpfApplication1 {
public partial class WindowBase : Window {
private static WindowBase instance;
static WindowBase() {
}
private WindowBase() {
Closed += AbstractWindow_Closed;
}
public static WindowBase Instance {
get {
if (instance == null) {
instance = new WindowBase();
} return instance;
}
}
private void AbstractWindow_Closed(object sender, EventArgs e) {
instance = null;
}
}
}
What exactly is the missing piece of the puzzle or am I going about this the wrong way?
Using the Singleton pattern on MainWindow is fine, but as #elgonzo said, your Instance property in the AboutWindow class that you have inherited from the WindowBase class returns an instance of WindowBase.
Furthermore, any derived class will automatically call the base class constructor when initialised, but your AboutWindow constructor is public and a public constructor cannot call the private constructor from the base class.
I have no idea why you're trying to do this instead of simply repeating the Singleton pattern in the AboutWindow class. If the case is that you only want to allow one window to be open, regardless of which window that is, then you'll have to use a different method... there is a really simple solution for that requirement and you can find it detailed in the How can I make sure only one WPF Window is open at a time? post here on StackOverflow.
I don't know if you need to access the MainWindow while the Window is open, but you can use ShowDialog() instead of Show().
Then you can't access the underlying window and can't open another one by clicking anything.
Got a problem with short cuts, any help/tips would be much appreciated!
Goal: I need to be able to handle short cut keys, with and without modifiers in my app.
So for instance i need to handle a key 'a' as well as 'CTR+a'. But I want to handle them only if no control handles these keys. For instance TextBox class takes most keys, including some commands like 'Ctrl+C' etc, so I don't want to intercept these events when TextBox will handle them.
I tried using Commands as well as attaching events to KeyUp to the Window, but, commands intercept keys before the TextBox gets a chance to view them, KeyDown bubbles to the Window level even if TextBox used the key! How can I get my window to get the keys that are NOT handled by any child control? Please see the code below that did not work for me. Also, since i have many different controls, I rather have a "proper" solution: I rather not attach handlers to each instance of a control in my window.
<Window x:Class="KeyTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Help"
CanExecute="HelpCanExecute"
Executed="HelpExecuted" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Help" Key="H" />
</Window.InputBindings>
<Grid>
<WrapPanel>
<TextBox Name="myLOG" Width="300" Height="200" Background="LightBlue" />
<TextBox Name="myINPUT" Width="300" Height="200" />
<Button Content="JUST FOR FUN" />
</WrapPanel>
</Grid>
And for C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace KeyTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private void HelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
myLOG.Text += "HELP CAN EXECUTE\n";
e.CanExecute = true;
e.Handled = true;
}
private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
myLOG.Text += "HELP EXECUTED!!!\n";
e.Handled = true;
}
public void myKeyUpHandler(Object sender, KeyEventArgs args)
{
myLOG.Text += "KEY UP EVENT! " + args.Key + "\n";
}
public MainWindow()
{
InitializeComponent();
this.KeyUp += new KeyEventHandler(myKeyUpHandler);
}
}
}
When the focus is in text box, pressing "h" triggers the command, even though i want 'h' to only go to the text box. Also, when inside textbox, pressing any alpha numeric key fires the KeyUp event, even though as far as I understand, textbox should have handled=true that event!
Thanks for help!
You need to investigate using the preview event types. They happen before other controls will handle the events. Then you want to stop the events bubbling. I belive you are doing that correctly with e.Handled.
Investigate this: http://msdn.microsoft.com/en-us/library/system.windows.input.keyboard.previewkeydown.aspx
Not sure how to do it in xaml for what you want to do. The expressions blend libraries can be quite helpful for spawning commands off of events. See here: http://jacokarsten.wordpress.com/2009/03/27/applying-command-binding-to-any-control-and-any-event/
Dude I think you need to use previewKeyDown or PreviewKeyUp Event instead of a keyup event here because PreviewKeydown and PreviewKeyup Event produce tunneling effect(OPPOSITE of bubbling effect where events where fired starting from the RootParent of the control which fired the event down the to control which originally fired the event(also know as original source)). you can take advantage of this tunneling effect for handling events rather that using events which are fired via bubbling effect. Another thing is that PreviewKeyDown and PrevieKeyup events where fired before keydown events occur. This could let you intercept the event in the cleanest way.
Another thing, I think you need to check the original source of the event so that you could select the controls that could fire this events.
Here is a sample code
public void nameOfCotrol_PreviewKeyDown(object sender, RoutedEventArgs e)
{
if((e.OriginalSource as Control).Name == "NameOfControls That would be allowed to fire the event")
{
You're stuff to be done here
}
else
{
e.handled = true;
}
}
I hope this could help in a small way. Thanks