Cannot create an instance of Usercontrol when subscribing an event - c#

There are other threads on the topic but I did not find any that are related to my specific problem.
In Visual Studio 2017, I have a situation when the XAML designer prompt an error even though nothing strange seems to be present.
Basically, to reproduce the problem, consider those two files,
MainWindow.xaml
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TabControl Background="White">
<TabItem Header="TEST" Width="60">
<local:UserControl1/>
</TabItem>
</TabControl>
</Grid>
</Window>
Usercontrol1.xaml.cs
namespace WpfApp1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
App.Current.MainWindow.Closing += window_Closing;
}
void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
}
}
}
Note that I did not include the content of Usercontrol1.xaml because it is not relevant here. It can be an empty UserControl.
Now, the designer shows the Error
Cannot create an instance of "Usercontrol1".
It is strange since when starting the application, everything is working fine. This is easily reproducible by creating a new WPF app and creating the same pattern shown above.
NOTE
I tried removing the subscription
App.Current.MainWindow.Closing += window_Closing;
And it removes the error. So, it is the cause, but why ?

App.Current will be null while in DesignMode.
You can check for IsInDesignMode to prevent running this code. Like,
public UserControl1()
{
InitializeComponent();
if(!DesignerProperties.GetIsInDesignMode(this))
App.Current.MainWindow.Closing += window_Closing;
}
Related post in MSDN blog.

Related

WPF: Problem with display xaml view inherits from UserControl

Hello i have this Viw in XAML
<local:JedenViewBase x:Class="Firma.View.FakturaView"
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:Firma.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary Source="MainWindowResource.xaml" />
</UserControl.Resources>
<Grid>
.....
</Grid>
</local:JedenViewBase>
And that is class this view
namespace Firma.View
{
public partial class FakturaView : JedenViewBase
{
public FakturaView()
{
InitializeComponent();
}
}
}
And that is JedenViewBase class
namespace Firma.View
{
public class JedenViewBase : UserControl
{
static JedenViewBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(JedenViewBase), new FrameworkPropertyMetadata(typeof(JedenViewBase)));
}
}
}
I have problem because view in XAML dont display, i dont know why? JedenViewBase class inherits from UserControl. When i UserControl in view everything works. What i should do?
<UserControl x:Class="Firma.View.FakturaView"
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:Firma.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary Source="MainWindowResource.xaml" />
</UserControl.Resources>
<Grid>
...
</Grid>
</UserControl>
View FakutraView when i use UserControl
I try rebuild app etc. and i still have problem
You've created a custom control.
That's unlikely to be a good idea and this should probably just be a user control.
The reason you get no view is this.
static JedenViewBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(JedenViewBase), new FrameworkPropertyMetadata(typeof(JedenViewBase)));
}
I recommend you remove that. Change
<local:JedenViewBase
To user control.
Make this just a user control.
Alternatively. Read up on custom controls. Put your ui definition in generic xaml.
I also wonder why this has it's own resources. They will be in memory for each instance. If whatever is in that resource dictionary is unique to this control maybe that's not a bad idea. in which case the naming seems strange.

RoutedCommand in UserControl is not working as expected

I am trying to use RoutedCommands in my UserControls, following the example in this article:
https://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/
I defined the RoutedCommand and CommandBindings in the UserControl instead of in the article's example. I am trying to use it in my MainWindow, so that when the Button is clicked, the Command in the UserControl is executed. However, the Button is disabled and the Foo_CanExecute() method is never executed.
<UserControl x:Class="RoutedCommandTest.ViewControl"
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:RoutedCommandTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.CommandBindings>
<CommandBinding
Command="{x:Static local:ViewControl.Foo}"
PreviewCanExecute="Foo_CanExecute"
PreviewExecuted="Foo_Executed"
/>
</UserControl.CommandBindings>
<Grid>
</Grid>
</UserControl>
Here is the code for ViewControl.xaml.cs:
public static readonly RoutedCommand Foo = new RoutedCommand();
void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
void Foo_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("The Window is Fooing...");
}
public ViewControl()
{
InitializeComponent();
}
And here is the code for MainWindow.xaml:
<Window x:Class="RoutedCommandTest.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:RoutedCommandTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:ViewControl/>
<Button Content="Foo" Margin="0 5" Command="{x:Static local:ViewControl.Foo}"/>
</Grid>
</Window>
I would like to know how to fix the issue so that the Button is enabled and the Foo_CanExecute() method is executed when the Button is clicked.
Your command is in a usercontrol, whilst the button is in mainwindow.
Which presumably contains your usercontrol.
Like bubbling and routing events ( which are used to drive them ).
Executed looks for the command bubbling UP the visual tree to the binding.
PreviewExecuted looks for the command tunnelling DOWN the visual tree to the binding.
Since your button is in the parent of the usercontrol I'm not sure whether either bubbling or tunnelling will work.
But tunnelling would be PreviewExecuted And PreviewCanExecute.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.commandbinding.previewexecuted?view=netframework-4.8
https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.commandbinding.previewcanexecute?view=netframework-4.8
Routedcommands can be pretty tricky to get right.
One thing you sometimes have to do is to bind commandtarget to tell it where to go look.
eg:
<Grid>
<local:UserControl1 x:Name="UC1" Height="60" Width="100"/>
<Button Content="Foo" TextElement.FontSize="30" Command="{x:Static local:UserControl1.Foo}"
CommandTarget="{Binding ElementName=UC1}"
/>
</Grid>
Works for me.
I have rarely found them useful - this is one of the aspects makes them way less useful than you might at first imagine.
EDIT:
It's perhaps worth mentioning the other thing makes these unattractive compared to a regular icommand. You need to either use a static which means it's only suitable for very generic commands OR you need event handlers which will be in code behind.
On the other hand.
If you're writing something has to work generically with whatever has focus. Like say a text editor with multiple textboxes and you're doing text manipulation. A routed command might be suitable. I have never encountered such a requirement in apps I've worked on though.

WPF C# Button Event Handler Not Working

I am having a problem getting and event handlers to work for a button. I am using Visual Studio 2015. My code and error is below:
XAML:
<Window x:Class="WpfApplication1.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:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="500" Width="983.334">
.
.
.
<Button x:Name="Button1" Content="Database" HorizontalAlignment="Left"
Margin="10,427,0,0" VerticalAlignment="Top" Width="99"
Click="Button1_Click"/>
Code behind:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Test");
}
}
}
Error:
CS1061 'MainWindow' does not contain a definition for 'Button1_Click' and no extension method 'Button1_Click' accepting a first argument of type 'MainWindow' could be found (are you missing a using directive or an assembly reference?)
Whenever I add a button and click on the event handler section this is what I see: The document item had no code-behind file. Add a code-behind file and a class definition before adding event handlers.
Any help would be appreciated.
It works for me for the following XAML
<Window x:Class="WpfApplication1.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:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="500" Width="983.334">
<Button x:Name="Button1" Content="Database" HorizontalAlignment="Left"
Margin="10,427,0,0" VerticalAlignment="Top" Width="99" Click="Button1_Click"/>
</Window>
and the following code behind file
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Test");
}
}
which is exactly what you have.
Have you tried rebuilding the solution?
Sound like the Event isn't registered in the page, click on your button and check the events tab to see if it's registered... check this image:
https://postimg.org/image/5q6nvac7b/

Why does Source for ContextMenuOpening behave differently for Canvas and UserControl?

I have a simple window:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfApplication1"
Title="MainWindow" Height="435" Width="613">
<StackPanel>
<Canvas Name="canvas">
<self:Red />
</Canvas>
<UserControl Name="uc">
<self:Blue />
</UserControl>
</StackPanel>
</Window>
Redand Blueare very simple UserControls:
<UserControl x:Class="WpfApplication1.Blue"
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="300" d:DesignWidth="300">
<Grid>
<Rectangle Fill="Blue" Width="100" Height="100" />
</Grid>
</UserControl>
I have created some ContextMenus:
public MainWindow()
{
InitializeComponent();
canvas.ContextMenu = new ContextMenu();
canvas.ContextMenuOpening += (sender, e) =>
{
System.Diagnostics.Debug.WriteLine(e.Source.GetType());
};
uc.ContextMenu = new ContextMenu();
uc.ContextMenuOpening += (sender, e) =>
{
System.Diagnostics.Debug.WriteLine(e.Source.GetType());
};
}
If I open the context menu on the Canvas, the Source is Red, but if I open it on the UserControl, Source is UserControl.
Any idea why?
I found this on MSDN:
ContextMenu itself is a FrameworkElement derived class, but this event will not be raised from the context menu being opened as a source. The event is raised from the element that "owns" the context menu as a property...
If I understand it correctly Source should be Canvas in the first case, but it isn't.
This behavior is covered fairly well in the MSDN documentation for the RoutedEventArgs.OriginalSource property:
Source adjustment by various elements and content models varies from class to class. Each class that adjusts event sources attempts to anticipate which source is the most useful to report for most input scenarios and the scenarios for which the class is intended, and then sets that source as the Source. If this source is not the one that has relevance to your handling of the event, try checking OriginalSource instead to see if it reports a different source that is more suitable.
Which is exactly what the UserControl class does, it patches the Source property in its AdjustBranchSource() method.
So, as hinted by the quoted text, you are perhaps looking for the OriginalSource property to make the code behave similarly, you'll get a reference to the Rectangle in both cases.

Setting <Window.DataContext> in XAML

I followed a very simple MVVM example as a basis for my program. The author had one code behind instruction he used in the main page to set the DataContext. I'm thinking I should be able to do this in the XAML instead. The MainWindowViewModel is in a directory ViewModels. The code behind works.
namespace RDLfromSP
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModels.MainWindowViewModel();
}
}
}
I can't seem to find the right combo to set it instead in the XAML
<Window x:Class="RDLfromSP.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300" >
<Window.DataContext>
<local:ViewModels.MainWindowViewModel />
</Window.DataContext>
Thanks in advance for your help
You'll need an xml namespace mapping to the ViewModels namespace. Once you add that, it would be:
<Window.DataContext>
<vms:MainWindowViewModel />
</Window.DataContext>
(This is assuming you map vms to the appropriate namespace.)
This should look just like your current namespace mapping for local:, but called vms: with the appropriate namespace specified.

Categories

Resources