I've just started with WPF a few days ago and have come to a problem I dont understand.
I got the following error:
Value cannot be null. Parametername: value
The error occurs here:
<Window.CommandBindings>
<CommandBinding Command="self:CustomCommands.Exit" Executed="ExitCommand_Executed" CanExecute="ExitCommand_CanExecute"/>
</Window.CommandBindings>
I've of course set namespace xmlns:self="clr-namespace:PrintMonitor" in the xaml.
The code-behind:
namespace PrintMonitor
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if(e != null)
e.CanExecute = true;
}
private void ExitCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown();
}
}
public static class CustomCommands
{
public static readonly RoutedUICommand Exit = new RoutedUICommand
(
"Beenden",
"Exit",
typeof(CustomCommands),
new InputGestureCollection()
{
new KeyGesture(Key.F4, ModifierKeys.Alt)
}
);
}
}
So why does this error occurs if I use a custom command but not if i use e.g. Command="ApplicationCommands.New" and how can I fix this error?
The Code is part of this tutorial.
Click on the button "Enable Project Code" Just under the designer window
Maybe you need to set the CustomCommands to not static,
and let the MainWindow's DataContext to be CustomCommands
public class CustomCommands
{
public static readonly RoutedUICommand Exit = new RoutedUICommand
(
"Beenden",
"Exit",
typeof(CustomCommands),
new InputGestureCollection()
{
new KeyGesture(Key.F4, ModifierKeys.Alt)
}
);
}
public partial class MainWindow : Window
{
public CustomCommands CM;
public MainWindow()
{
CM = new CustomCommands();
this.DataContext = CM;
InitializeComponent();
}
private void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if(e != null)
e.CanExecute = true;
}
private void ExitCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown();
}
}
I had this problem, then I just cleaned then built the solution and it was gone. For future reference i found that many problems with WPF using Visual Studio are just solved by clean then build, no idea why these issues happen more frequent with WPF + VS.
Related
Here is how it should work:
Window1: A button click opens a new window and hides the current window
(This page contains a few textboxes)
public void applyBtn_Click(object sender, EventArgs e)
{
...
DataDisplay dd = new DataDisplay();
dd.Visibility = Visibility.Visible;
...
}
New Window: A button click opens Window1 from the same state (all the checkboxes, and textbox should contain the values from the time it was closed)
private void settings_btn_Click(object sender, RoutedEventArgs e)
{
Filters filter = new Filters();
filter.Visibility = Visibility.Visible;
}
//As you can see I am calling a new instance instead of reopening the same hidden instance.
Instead of creating a new instance every time, I'd prefer to use the same instance every time. If any other not so complicated ways out there, feel free to shoot!
If I understand you correctly, I think it would be better to have a "MainWindow" managing the 2 changing windows You could have it handled on the 2 Windows events or by using delegates:
public partial class MainWindow : Window
{
static frmFilters filterWindowInstance = new frmFilters(OpenDataDisplay);
static frmDataDisplay dataWindowInstance = new frmDataDisplay(OpenFilters);
static void OpenFilters()
{
filterWindowInstance.Visibility = Visibility.Visible;
dataWindowInstance.Visibility = Visibility.Collapsed;
}
static void OpenDataDisplay()
{
filterWindowInstance.Visibility = Visibility.Collapsed;
dataWindowInstance.Visibility = Visibility.Visible;
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
OpenFilters();
Visibility = Visibility.Collapsed;
}
}
public partial class frmFilters : Window
{
Action CloseFilterOpenData;
public frmFilters(Action CloseFilterOpenDataToSet)
{
InitializeComponent();
CloseFilterOpenData = CloseFilterOpenDataToSet;
}
private void cmdHideThis_Click(object sender, RoutedEventArgs e)
{
CloseFilterOpenData();
}
}
public partial class frmDataDisplay : Window
{
Action CloseDataOpenFilter;
public frmDataDisplay(Action CloseDataOpenFilterToSet)
{
InitializeComponent();
CloseDataOpenFilter = CloseDataOpenFilterToSet;
}
private void cmdHideThis_Click(object sender, RoutedEventArgs e)
{
CloseDataOpenFilter();
}
}
I have got the following setup for my commands. I can't seem to figure out how I reference the window which my button is on, so that I can close it.
Is there some way I can use the command arguments ExecutedRoutedEventArgs e to reference the window and close it?
Button (on MainWindow.xaml)
<Button Command="Commands:MyCommands.CloseWindow">✖</Button>
Here are my commands, which are located in
Classes > Commands.cs
namespace Duplicate_Deleter.Classes
{
public class MyCommands
{
private static RoutedUICommand _CloseWindow;
private static RoutedUICommand _MinimizeWindow;
static MyCommands()
{
_CloseWindow = new RoutedUICommand("Close current window",
"CloseWindow", typeof(MyCommands));
_MinimizeWindow = new RoutedUICommand("Minimize current window",
"MinimizeWindow", typeof(MyCommands));
}
public static void BindCommandsToWindow(Window window)
{
window.CommandBindings.Add(
new CommandBinding(CloseWindow, CloseWindow_Executed, CloseWindow_CanExecute));
window.CommandBindings.Add(
new CommandBinding(MinimizeWindow, MinimizeWindow_Executed, MinimizeWindow_CanExecute));
}
// Command: CloseWindow
public static RoutedUICommand CloseWindow
{
get { return _CloseWindow; }
}
public static void CloseWindow_Executed(object sender,
ExecutedRoutedEventArgs e)
{
//Close window using e?
}
public static void CloseWindow_CanExecute(object sender,
CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
// Command: MinimizeWindow
public static RoutedUICommand MinimizeWindow
{
get { return _MinimizeWindow; }
}
public static void MinimizeWindow_Executed(object sender,
ExecutedRoutedEventArgs e)
{
MessageBox.Show("Minimize Window");
}
public static void MinimizeWindow_CanExecute(object sender,
CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
}
}
I bind the commands using a customized startup in
App.xaml.cs
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
//Bind Commands
Classes.MyCommands.BindCommandsToWindow(main);
}
}
I tried this way and it works for me:
private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
var dObj = e.Source as DependencyObject;
if(dObj == null) return;
var parentWindow = dObj.GetVisualParentOfType<Window>();
if(parentWindow == null)
return;
parentWindow.Close();
}
Helper:
public static T GetVisualParentOfType<T>(this DependencyObject child)
where T : DependencyObject
{
var parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
var parent = parentObject as T;
return parent ?? GetVisualParentOfType<T>(parentObject);
}
keep in mind that the helper method is an extension method that, put it in public static class.
regards
I am making an WPF application. I have a datagrid with static items in it. For now I want to show a new window when clicked on a row.
What am I doing wrong?
This is my second Window I want to open when clicked: WindowMail.cs
using System;
namespace Phish_Finder
{
internal class WindowMail
{
internal void Show()
{
WindowMail wm = new WindowMail();
wm.Show();
}
}
}
This is the method in my first window Mainwindow.xaml.cs
private void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e)
{
var currentRowIndex = URLGRID.Items.IndexOf(URLGRID.CurrentItem);
{
if (URLGRID.CurrentItem != null)
{
WindowMail wm = new WindowMail();
wm.Show();
}
}
}
And this is my datagrid
DataGrid x:Name="URLGRID" HorizontalAlignment="Left" Height="400"
Margin="60,300,0,0" VerticalAlignment="Top" Width="1350" Loaded="DataGrid_Loaded"
MouseDoubleClick="DataGrid_MouseDoubleClick"
I am new to WPF and I think that I am mixing up where I should put methods. But I am not sure.
Use the following code
private void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e)
{
var currentRowIndex = URLGRID.Items.IndexOf(URLGRID.selectedItem);
{
if (URLGRID.selectedItem != null)
{
WindowMail wm = new WindowMail();
wm.Show();
}
}
}
perhaps the code
internal class WindowMail
{
internal void Show()
{
WindowMail wm = new WindowMail();
wm.Show();
}
}
needs a little change. I here believe that the class WindowMail is actually the cs class after the WindowMail.xaml file.
Here you need to change the
WindowMail wm = new WindowMail();
wm.Show();
lines into
this.Show(); //Standard function of a window
else your code keeps on repeating Infinite loop...
Also, things you need to change: I believe the function Show already exists on the window level. So rename it like below or do an override of the function.
public void OpenDialog(bool asDialog)
{
if(asDialog)
this.ShowDialog();
else
this.Show();
}
Then, for calling your function:
private void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e)
{
if (URLGRID.SelectedItem!= null)
{
WindowMail wm = new WindowMail();
wm.OpenDialog(true);
}
}
I've got a AddWindow to add new client, the MainWindow (which is always showed) and I want to send the information from Addwindow to ListBox in MainWindow (I mean i need to add new item to listbox).
Someone knows how can I do that?
You can do that with events of that object like this :
public partial class AddWindow : Window
{
public AddWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (Check != null)
Check(TextBox.Text);
}
public event Action<string> Check;
}
and in main window
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
AddWindow popup = new AddWindow();
popup.Check += popup_Check;
popup.Show();
}
void popup_Check(string obj)
{
ListBox.Items.Add(obj);
}
}
I had implemented a wpf combobox into a winform and now have to somehow make it call a function or an event in my winform when the box is changed, as well as be able to change the value from the winform.
main:
namespace main
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ElementHost elhost = new ElementHost();
elhost.Size = new Size(174, 24);
elhost.Location = new Point(93,60);
MyWPFControl wpfctl = new MyWPFControl();
elhost.Child = wpfctl;
this.Controls.Add(elhost);
elhost.BringToFront();
}
public void status_change(int val)
{
MessageBox.Show("Box value has changed to:" + Convert.ToString(val) );
}
and wpf:
namespace main
{
/// <summary>
/// Interaction logic for MyWPFControl.xaml
/// </summary>
public partial class MyWPFControl : UserControl
{
public MyWPFControl()
{
InitializeComponent();
}
private void statComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
main.status_change(statComboBox.SelectedIndex);
/// says:
/// Error 1 The type or namespace name 'status_change' does not exist in the namespace 'main' (are you missing an assembly reference?) C:\Users\Robert\documents\visual studio 2010\Projects\XMPP\main\wpf_combo_status.xaml.cs 31 18 main
}
}
}
any idea what I might be doing wrong? Thanks!
Expose an event in MyWPFControl like:
public SelectionChangedEventArgs:EventArgs
{
public int SelectedIndex {get; private set;}
public SelectionChangedEventArgs (int selIdx)
{
this.SelectedIndex = selIdx;
}
}
public partial class MyWPFControl : UserControl
{
public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
public MyWPFControl()
{
InitializeComponent();
}
private void statComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
OnSelectionChanged(statComboBox.SelectedIndex);
}
private void OnSelectionChanged(int selIdx)
{
if (SelectionChange != null)
SelectionChanged(this, new SelectionChangedEventArgs(selIdx));
}
}
Then subscribe it in your form, like:
public Form1()
{
InitializeComponent();
ElementHost elhost = new ElementHost();
elhost.Size = new Size(174, 24);
elhost.Location = new Point(93,60);
MyWPFControl wpfctl = new MyWPFControl();
elhost.Child = wpfctl;
this.Controls.Add(elhost);
elhost.BringToFront();
wpfctl.SelectionChanged += myWPFControls_SelectionChanged;
}
private void myWPFControls_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
status_change(e.SelectedIndex);
}
P.S.:
I can't test it, so there could be some errors, but just to give you the idea... ;)
It's hard to say without more context, but it would seem that the code you want is probably:
private void statComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
main.status_change(statComboBox.SelectedIndex);
}
Assuming main is the instance of Form1 on which you want to call status_change.