In my WPF Program (I'm using MVVM Pattern) I have a simple button with its command.
When user click on this button the command execute method is called and a new Window is created.
In this application there are two ways to open this window: left mouse click and shitf + left mouse click on the same button.
The difference is the follow: by left mouse click the "Advanced" tab of my tabcontrol in my window isn't showed, else, by left mouse click + shift the "Advanced" tab is showed.
I have implemented this logic but i think that this isn't the best way to do it. This is the code:
Execute method of my Command:
private void OptionsExecute()
{
var isAdvancedTabVisibile = false;
if (Keyboard.Modifiers == ModifierKeys.Shift)
{
isAdvancedTabVisibile = true;
}
_windowFactory.OpenOptionsWindow(isAdvancedTabVisibile);
}
XAML (Using the name of properties):
<dx:DXTabControl Margin="5" Name="myTabControl">
<dx:DXTabItem Header="Avanzate" Name="advanced">
…
</dx:DXTabItem>
</dx:DXTabControl>
C# utility method to open Window (Following MVVM Pattern):
public void OpenOptionsWindow(bool isAdvancedTabVisible)
{
OptionsWindow window = new OptionsWindow();
var tabCollection=window.myTabControl.Items;
var tabList=tabCollection.Cast<DXTabItem>().ToList();
if (isAdvancedTabVisible)
{
tabList.FirstOrDefault(ti => ti.Name == "advanced").Visibility = Visibility.Visible;
}
else
{
tabList.FirstOrDefault(ti => ti.Name == "advanced").Visibility = Visibility.Collapsed;
}
window.ShowDialog();
}
My question is: there is a better way to do the same thing? A way by setting a flag property in my ViewModel and bind the tabitem Visibility to this property? Any other suggestion?
Thanks.
Related
I want to rebind the "Up" key for my window to perform a command on my ViewModel.
My window contains 2 controls: ListView, TextBox.
If I do
<Window.InputBindings>
<KeyBinding Key="F5" Command={Binding SomeCommand} />
</Window.InputBindings>
Everything works correctly. However, if I set it to "Up", or certain other keys, the command does not get executed if the TextBox has focus. This tells me that the TextBox is handling these keys and swallowing the event that triggers the command. Is there any way to prevent that and to allow the window to get them similar to the Preview events (PreviewKeyUp) ?
If you want an application level shortcut, you can use InputManager
InputManager.Current.PreProcessInput += (sender,args)
{
var keyboardEvent = args?.StagingItem?.Input as KeyboardEventArgs;
if(keyboardEvent != null)
{
var keyArgs = keyboardEvent.RoutedEvent as KeyEventArgs;
if(keyArgs != null)
{
if(keyArgs.Key == Key.F5)
{
// Do something
}
}
}
};
I would recommend taking the logic above and incorporating it into a behavior that you can bind/map Keys to Commands.
Is there any way to prevent that and to allow the window to get them similar to the Preview events (PreviewKeyUp) ?
You could hook up an event handler to the KeyDownEvent using the overload of the AddHandler method that accepts a "handledEventsToo" boolean parameter and invoke your command from this event handler:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
DataContext = vm;
AddHandler(KeyDownEvent, new KeyEventHandler((ss, ee) =>
{
vm.SomeCommand.Execute(null);
}), true);
}
}
There is no way to do this in pure XAML though but it doesn't really matter as far as the MVVM pattern is concerned as you simply move the invocation of the command from the XAML markup of the view to the code-behind class of the very same view. This doesn't break the MVVM pattern.
What is this: I am building a media application to allow the user to view files and open them. For right now, I only have one category, which is movies.
Intro to the problem (What I am trying to accomplish): I have a full screen button, that once clicked will make the movie full screen to the frame (Page) and the window of the whole application will also full screen (borderless).
The problem: My problem as hinted through the text is to full screen the movie to the whole application, not just frame. I have an idea of how to get the application window, through the following code, but I am unable to find out how to select the frame of the application, and resize its contents to the application when the user clicks the button to fullscreen.
(Its kind of annoying seeing bits of the application around the actual movie/media, and the hamburger menu):
VideoPlayer page button click event for fullscreen button:
private void Fullscreen_Click(object sender, EventArgs e)
{
var wnd = Window.GetWindow(this);
if (Player.Height == System.Windows.SystemParameters.PrimaryScreenHeight && Player.Width == System.Windows.SystemParameters.PrimaryScreenWidth)
{
wnd.WindowState = WindowState.Normal;
wnd.WindowStyle = WindowStyle.SingleBorderWindow;
Player.Width = (double)Application.Current.Properties["VideoWidth"];
Player.Height = (double)Application.Current.Properties["VideoHeight"];
}
else if (Player.Height != wnd.Width && Player.Width != System.Windows.SystemParameters.PrimaryScreenWidth)
{
;
wnd.WindowState = WindowState.Maximized;
wnd.WindowStyle = WindowStyle.None;
Player.Width = wnd.Width;
Player.Height = wnd.Height;
}
My MainWindow x:Name - "HomeWindow" and class - "MainWindow"
Frame x:Name="Home"
OR if I can't resize the frame or use it, at least access the other elements like the hamburger menu and inside the event, make those elements hidden.
Any help will be much appreciated!
I have a form done in WPF which has a custom control already on it called RateView. This custom control has 4 textboxes (which are all working as they should be). It also contains a button.
I have a second custom control called Extended Margin Info, which also has a XAML Form which will just show output data only.
How can I by clicking the button on the custom control called Rateview bring up the XAML canvas onto my Main window of the extendedmargin info XAML, in the same position everytime? Rateview control exists 5 times on the main window therfore there will be 5 buttons that when clicked, will need to output the popup of ExtendedMargin Info to the main screen in the same position each time with the content of extendedmargin info.
Your button, when clicked, should call a Command which updates a Property of some ViewModel that exposes the ViewModel of the current ExtendedMarginInfo you want to display. Then you can bind this property to the Content Property of a ContentControl in the target view. You can select the View you want the Control to display by using the ContentControl.ContentTemplateSelector property.
I guess you want show one popup and change it's content placing in it different controls.
At 1st create your custom control:
balloon = new LogEntryInfoBalloon();
balloon.SetMainWindow(this);
balloon.DataContext = vm.NotificationViewModel;
Then create Popup control (System.Windows.Controls.Primitives):
localPop = new Popup();
localPop.AllowsTransparency = true;
localPop.Placement = PlacementMode.AbsolutePoint;
localPop.StaysOpen = true;
localPop.PlacementTarget = this;
localPop.Child = balloon;
Placement target points to MainWindow.
Define timer that will close(hide) balloon:
localPopTimer = new Timer(new TimerCallback(CloseLocalPopup));
Close func:
private void CloseLocalPopup(object args)
{
var act = new Action(() =>
{
localPop.IsOpen = false;
});
Dispatcher.BeginInvoke(act, null);
}
Show balloon code looks like this:
private void ShowNotifyBaloon(NotifyBaloonViewModel vm)
{
var act = new Action(() =>
{
localPop.IsOpen = true;
localPopTimer.Change(4000, Timeout.Infinite);
});
Dispatcher.BeginInvoke(act, null);
}
I have a TreeView control for which each node in it I want to share a ContextMenuStrip which has two ToolStripMenuItems ie:
this.BuildTree = new MyApp.MainForm.TreeView();
this.ItemMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowLogMenuItem = new System.Windows.Forms.ToolStripMenuItem();
...
this.ItemMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteMenuItem,
this.ShowLogMenuItem});
So I show and hide these to items according to certain criteria on a right click in a MouseUp event. When both are hidden I hide the ContextMenuStrip itself. Problem is when I hide the ContextMenuStrip it seems the next time I want to show one of the menu items I have to click twice on the node. The strange thing is on the first click to reshow one or both of the the items I have the following code:
ItemMenuStrip.Visible = true;
ShowLogMenuItem.Visible = true;
The two lines above don't seem to do anything ie both remain false in the debugger view after stepping over each line.
I don't think I've got any events on these values being set at least I don't have any events attached.
What am I doing wrong?
I suggest you to set:
this.BuildTree.ContextMenuStrip = this.ItemMenuStrip;
to make the menu automatically open on tree right-click.
Then subscribe ItemMenuStrip.Opening event to change the visibility of items and the contextmenu itself:
void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
if (something)
{
e.Cancel = true; // don't show the menu
}
else
{
// show/hide the items...
}
}
If you need to know the current position of the clicked point (e.g. to check if a tree node is clicked), you can use Control.MousePosition property. Note that MousePosition is a point in screen coordinates, so you need to call treeView1.PointToClient(position) to get the tree coordinates e.g. :
private void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
var pointClicked = this.BuildTree.PointToClient(Control.MousePosition);
var nodeClicked = this.BuildTree.GetNodeAt(pointClicked);
if (nodeClicked == null)
{
// no tree-node is clicked --> don't show the context menu
e.Cancel = true;
}
else
{
// nodeClicked variable is the clicked node;
// show/hide the context menu items accordingly
}
}
So figured out what was going wrong I was setting Visible on this.ItemMenuStrip rather than the this.BuildTree.ContextMenuStrip.
This seems rather strange to me as I would have thought BuildTree.ContextMenuStrip was just a direct reference to the ItemMenuStrip but apparently not.
I am new to WPF, my problem is that I have a top menu as UserControl added in the main window and the main window is split into three columns: in the right most column I have a DockPanel, now my problem is that I don't know how to add another control in that right column when I click on the top menu item.
Some code, to illustrate my attempt:
public partial class TopMenu : UserControl
{
private void menuItem_Click(object sender, RoutedEventArgs e)
{
SecondControl ctrl = new SecondControl();
Window1 winMain = new Window1();
winMain.dp3.Children.Add(ctrl ); // dp3 is the dock panel in the right column of
}
}
Now, what should I do to display that control on window1?
The problem is that you're adding the control to the DockPanel of a new instance of a Window1 window. You will need to 'find' the instance of the Window1 type in which the your TopMenu control is embedded.
Using the code from here we can find the top-level control, your window, and then add the controls to that instance:
private void menuItem_Click(object sender, RoutedEventArgs e)
{
var topLevelControl = GetTopLevelControl(this);
if (topLevelControl != null && topLevelControl is Window1)
{
var currentWindow = topLevelControl as Window1;
SecondControl ctrl = new SecondControl();
currentWindow.dp3.Children.Add(ctrl );
}
}
DependencyObject GetTopLevelControl(DependencyObject control)
{
DependencyObject tmp = control;
DependencyObject parent = null;
while((tmp = VisualTreeHelper.GetParent(tmp)) != null)
{
parent = tmp;
}
return parent;
}
Because you are new to WPF I recommend that you invest some time learning MVVM, binding, INotifyPropertyChanged interface etc.
Good resources are:
NYC DevReady: MVVM - Session 1 (of 5) - Demystifying XAML
NYC DevReady: MVVM - Session 2 (of 5) - Programming with MVVM - Part 1
NYC DevReady: MVVM - Session 3 (of 5) - Programming with MVVM - Part 2
You could solve your problem in multiple ways. For example, you could put ContentControl to the right column where you want to show your SecondControl. Now, when you want to show your SecondControl just fill Content property of the ContentControl with the SecondControl