I'm having a WPF application which I can minimize to tray. When I normal-click it, the window shows again.
Now I'm wondering how to create a simple ContextMenu?
The ContextMenu has to get filled with x options which onclick will run a function. For now I just need an 'Exit'-item linked to an 'Exit_Click' method.
Something I've tried is:
ContextMenu menu = (ContextMenu)this.FindResource("NotifierContextMenu");
menu.IsOpen = true;
menu doesn't know of any IsOpen value.
Other examples like to use a lot of different things. One of them requires me to create a HostManager for some reason.
I just need a simple ContextMenu. How can I achieve this?
As #H.B. mentioned Hardcodet's NotifyIcon is pretty darn good for WPF Taskbar icons. Sucks you don't get that out of the box with WPF but you might as well use it and address your issue than wait for Microsoft to fix it(They really should just add that library into standards)
Now to solve your issue(Using above solution):
Download the solution
Build the library
Add it to your source control if you have one and add a reference to it(Hardcodet.Wpf.TaskbarNotification.dll) in your project
Now in your MainWindow.xaml you could just have something like:
<Window ...
xmlns:tb="http://www.hardcodet.net/taskbar"
...>
...
<Grid>
<tb:TaskbarIcon>
<tb:TaskbarIcon.ContextMenu>
<ContextMenu>
<MenuItem Click="Exit_Click"
Header="Exit" />
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
</tb:TaskbarIcon>
...
</Grid>
</Window>
and MainWindow.xaml.cs with the click handler like you needed:
private void Exit_Click(object sender, RoutedEventArgs e) {
Application.Current.Shutdown();
}
I do recommend spending some time looking at the examples coming with the source code of the library to familiarize yourself with your available options. Trust me wpf has it way too easy when it comes to helper libraries. Try some of qt helper libraries and you'll know what "buried in there somewhere" literally means in opensource helpers.
Related
I am creating a custom ToolBar control that I will be able to use in my WPF application.
My CustomToolBar control is based on a StackPanel control and will contain multiple CustomToolBarButton controls.
My CustomToolBarButtons are based on a vertical StackPanel and contain an Image control and a Label control.
I want to programmatically create a Click event for my CustomToolBarButtons that will fire when Image or label gets clicked. Unfortunately, neither Image nor Label controls have Click events in WPF.
It's a surprise for me because I am used to WinForms controls and vast majority of them have Click events by default. Do I have to create custom Image and Label controls and create Click events for them or is there a cleaner and simpler way of doing this?
Thanks for any help!
Well, there's not a great and simple way using standard functionality. I got around this by making my own trigger (derived from System.Windows.Interactivity.TriggerBase from the Blend SDK) so that in my projects I can do the following:
<Label>
<i:Interaction.Triggers>
<mu:MouseTrigger MouseButton="Middle" MouseAction="Click">
<i:InvokeCommandAction Command="{Binding Path=Close}" />
</mu:MouseTrigger>
</i:Interaction.Triggers>
</Label>
Effectively the MouseTrigger class will handle MouseDown and MouseUp events from the UIElement it's attached to and use that to invoke the actions associated with the trigger. The code is a bit more complex than just that, though, since I also do mouse capturing & I utilize an internal helper class so that I could add multiple triggers to the same element with only one instance of a helper class handling events & capturing the mouse for that element.
For the actual actions, I just use existing Blend or Prism actions such as InvokeCommandAction.
Here is the project if you're interested. It was too large to paste into this format. It uses some C# 6.0 features but you could easily modify it to work on an older version of C# by removing some null conditional operators. It requires you install the Blend SDK as it depends on System.Windows.Interactivity (should install with Visual Studio as long as you select that option). MouseTrigger is the publicly visible class that is the point of interaction with the functionality. MouseCatcher is the internal helper class mentioned.
I'd recommend not going down the route of custom controls, but rather of using some mechanism (this one or otherwise) to extend the existing functionality using the attached property framework that WPF and XAML bring to the table.
In WinForms you would create custom controls simply to get a nonstandard look, in WPF this is no longer necessary.
The WPF way: instead of making a Stackpanel's children implement Click behaviour, let's make a Button look like the desired Stackpanel.
Could do this setting the Content:
<Button>
<StackPanel >
<Image Source="C:\myFiles\myPic.png"/>
<Label HorizontalAlignment="Center">SomeTxt</Label>
</StackPanel>
</Button>
But this way it still looks like a Button, to overcome this we can set the Template instead:
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<StackPanel >
<Image Source="C:\myFiles\myPic.png"/>
<Label HorizontalAlignment="Center">SomeTxt</Label>
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
Both solutions will raise a Click event clicking the image or label.
I am working with C# in MS Visual Studio Community 2013. I am trying to set up a MenuItem so that when clicked it causes the current window to hide itself and another window appears at the same location.
I have a couple of books on the subject and I've also spent lots of time searching for answers online. However, I simply can't find out how to set this up when it's something that should be relatively straightforward to do.
I've done it before with older versions of C#, but it just seems impossible to sort out with Visual Studio Community 2013.
At this stage I have a menu and menu items set up something like the 'much simplified' following:
<Menu HorizontalAlignment="Left" Height="21" Margin="10,10,0,0" VerticalAlignment="Top" Width="1264" Grid.ColumnSpan="2" FontWeight="Medium" FontSize="14">
<MenuItem Header="Item Type" Margin="0" Width="100" Height="21" FontSize="11" Click="MenuItem_Click">
<MenuItem Header="Item Action" HorizontalAlignment="Left" Width="185"/>
</MenuItem>
</Menu>
Most, if not all of that was generated automatically, as I set up the menu in Visual Studio.
Also, if I right click on the 'Item Action' menu item, a popup appears with a 'view code' option. If I click that option, the following empty function appears in the corresponding *.cs file:
private void MenuItem_Click(object sender, RoutedEventArgs e) { }
I realise that I probably need to add code to that empty method to do what I need to do, but so far I haven't found out how to do that.
There is also a 'Command' property in the properties list for the MenuItem. I also assume that that may play a part in sorting this out, but at this stage I don't know how.
Please let me know how this needs to be set up and big thanks in advance for any help.
Also, after searching elsewhere on stackoverflow, I found the basics for hiding/showing different windows. I've got that working OK, but it's not enough to resolve my problem.
Basically, in my real menu I have multiple menuItems and the clicking of each one needs to be dealt with in a different way. Therefore, in the MenuItem_Click function I need a way of identifying which MenuItem was actually clicked, so that I can respond in the correct way for each and every MenuItem click.
You can add click event for each menu item and add code for each method.inside this method you can add this code
Window1.Visibility = Visibility.Hidden;
window2.Visibility = Visibility.Visible;
you can use Command property when you need to bind methods in MVVM Pattern
I am pretty new to WPF, and in order to get some knowledge I decided to make a very simple UML modeling program, that basically offers the possibility to put some classes onto a canvas, connect them and move them around.
Now to the question:
I have been thinking about letting the classes I put on the canvas being a userControl I design. In my mind it would be something like a Grid, with some textboxes to represent properties, attributes and so on. The actual question is then, is my idea possible, or should I go with something completely different? My concern right now is how to implement the grid such that it can expand (add a row) under the right heading (Attribute/property..) when I want it to, and not be expanded to a maximum from the beginning.
I hope you can understand my question, and give me an idea to whether I should continue to implement it how I thought about, or do it using some other method.
You may wish to consider a ListView control, perhaps with an Expander, something like this:
<Canvas>
<Expander Header="Stuff"
MaxHeight="900"
Canvas.Left="202"
Canvas.Top="110">
<ListView Name="MyListView">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Add new thing"
Click="MenuItem_Click" />
</ContextMenu>
</ListView.ContextMenu>
<ListViewItem>
<StackPanel Orientation="Horizontal">
<Label>Name</Label>
<TextBox Text="Value" />
</StackPanel>
</ListViewItem>
<ListViewItem>Item two</ListViewItem>
<ListViewItem>Item three</ListViewItem>
</ListView>
</Expander>
</Canvas>
This will size as needed up to the max given. The list view items could contain any sort of content (not just text) as you can see above. You will want to learn a bit about Style and Control templates. WPF has IMHO a rather steep learning curve but there are a lot of learning resources on the web. Good luck.
In response to your comment, I'm adding additional information.
Anything you can do in XAML you can do in code behind (mostly XAML just calls framework objects). In this case I've added a context menu to the ListView control. This menu contains one item "Add new thing". There is a Click event for this item which is bound to the MenuItem_Click method in the code behind. I then added this method to the code:
void MenuItem_Click(object sender, RoutedEventArgs e) {
var lvi = new ListViewItem();
lvi.Content = String.Format("New thing {0}", DateTime.Now);
MyListView.Items.Add(lvi);
}
Now if you right click in the ListView you will see the "Add new thing" menu selection, left clicking it adds a new ListViewItem into the ListView (programmatically).
I want to add a behaviour to a TextBlock in silverlight 3.
I have a behaviour class in a c# file in a different project than my xaml file within my solution.
public class FooBehavior : Behavior<TextBlock>
{
...
}
How do I attach this behaviour to my TextBlock? Would be nice to do without involving c# code.
Include the following lines in the definition of your UserControl:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:myBehaviors="clr-namespace:MyNamespace.Behaviors;assembly=MyAssembly"
Then on the TextBlock have this code:
<TextBlock .....>
<i:Interaction.Behaviors>
<myBehaviors:FooBehaviour/>
</i:Interaction.Behaviors>
</TextBlock>
ChrisF has the correct answer for how to write the Xaml to add the behavior. However, if you have Blend it is even simpler.
Open your project in Blend
On the tools toolbar click the >> button
Click on Behaviors
Find your Behavior and Drag it over your TextBlock and drop it
Blend will add all the proper namespaces for you.
I have followed the Accepted Answer's instructions from this post as regards creating a code behind file for a Resource Dictionary, and it worked...so now I can attach events to controls in the generic.xml file.
But now I want to be able to call the DragMove() method from an event in there and since there aren't any references to the window hosting the dictionary at the time, I don't know how to call this DragMove() method.
So, from a Resource Dictionary Code behind file, is there any way I can make a reference to the window that will currently be hosting that Resource Dictionary?
[Update] (Temporary Solution)
As a simple (yet stupid) workaround, I have currently done the following:
Since I can reference the Application.Current.MainWindow from the Generic.xaml.cs code-behind, I now have this in the Generic.xaml.cs:
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Application.Current.MainWindow.DragMove();
}
And then I'm attaching PreviewMouseLeftButtonDown handler to each Window I have, like such:
private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Application.Current.MainWindow = this;
}
It, well, it works...and until someone can come up with the proper way on how to do this, It should serve me well enough.
There is no way I know of doing this. However, if you're trying to determine the Window given a specific resource, you could use a RelativeSource:
<SolidColorBrush x:Key="MyBrush" Color="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource WindowToColorConverter}"/>
And if you're doing it from code, you can use Window.GetWindow(). You just need a DependencyObject hosted in that Window.
From architectural point of view I would say you are about to break the paradigm. It might be a bad decision providing Resource Dictionary with notion of UI that consumes it and giving some logic other than providing resources.
You might want some Adapter between UI and resource dictionary, or Controller if this is really needed to wire Resource Dictionary but again you shouldn't inject any logic in a resource container...
You can access your main window through
Application.Current.MainWindow
Hope this helps