I changed my UserControl to be a ReactiveUserControl and now I can't view the Design View. Is there anything I can do to get the designer to work with ReactiveUserControl?
The Visual Studio designer has issues when your control or window directly inherits from a generic class. This was a pretty common issue with WinForms as well. You can work around this issue by defining another non-generic class that sits between the generic ReactiveUserControl and your control:
public partial class MyUserControl : MyUserControlBase
{
public MyUserControl()
{
InitializeComponent();
}
}
public abstract class MyUserControlBase: ReactiveUserControl<MyUserControlViewModel>
{
}
In the XAML, our root object element is defined as the base element (MyUserControlBase) and its class declaration is connected to the partial class defined above (MyUserControl):
<myNameSpace:MyUserControlBase
x:Class="MyNameSpace.MyUserControl"
xmlns:myNameSpace="clr-namespace:MyNameSpace"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
Related
I'm trying to use a C# class derived from UserControl as the base class for some xaml pages' layout root, so I can share some common functionality. I.e. the backing class is like:
public class BaseView : UserControl
{
// Some virtual functions I want in common ...
}
public class MyView : BaseView
{
// Overidden functions ...
}
The xaml file then references the class like:
<jt:BaseView x:Class="ns.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jt="clr-namespace:ns"
...>
</jt:BaseView>
This seems to work when running, but in the xaml editor, the code is all underlined with blue squiggly lines, with a fly-over message of something like "Cannot create instance of BaseView".
If I don't do this, and use UserControl in the xmal, I get errors because the partial class generated from the xaml then has the UserControl base class and not my custom base class.
How do I get the editor to know about my custom base class (i.e. get rid of the blue underlines)?
The most common cause for a design time "Cannot create instance..." sort of error is that the constructor of the element is doing something that doesn't make sense or is unavailable at design time.
Using DI into MainView is not problem:
I added my windows into my container and on start up I show my windows that has been pulled out from my container. But If I have a usercontrol added into my main view as xaml tag, wpf view engine it will create automatically new instance for it without pulling out the UserControl I added into my container as well.. How can I force WPF view engine to search component required by view/xamal into my container instead of creating new one?
There is no way to do it without modifying your XAML. You can think about some workarounds, for example create a control inherited from ContentControl which will inject dependencies into its Content but I would not recommend this approach, only if you have no choice.
What I would recommend is to use the best WPF pattern - MVVM. The idea is to have a hierarchy of ViewModels, all of them will be created using IoC container with proper constructor injection. Also you will have hierarchy of views, each view will depend only on corresponding viewModel which will be passed into view's DataContext. This approach will allow you to use DI in WPF application nicely.
I think I understood what you suggested me
<Window x:Class="DDDSample02.Wpf.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:presentation="clr-namespace:DDDSample02.Wpf.Views"
Title="MainWindow" Height="384" Width="821">
<Grid>
<presentation:ProductsView DataContext="{Binding Path=ProductsPresenter}" />
</Grid>
</Window>
where MainWindow is pulled out from container at startup
protected override void OnStartup(StartupEventArgs e)
{
GuyWire.Wire();
((Window)GuyWire.GetRoot()).Show();//MainWindow
}
and Mainwindow looks like
public partial class MainWindow : Window
{
public MainWindow(DDDSample02.ViewModel.MainWindowPresenter presenter)
{
InitializeComponent();
this.DataContext = presenter;
}
}
public class MainWindowPresenter
{
public MainWindowPresenter(ProductsPresenter productPresenter)
{
this.ProductsPresenter = productPresenter;
}
public ProductsPresenter ProductsPresenter { get; private set; }
}
I'm working on a project that has several WPF User Controls that inherit from an abstract base class (itself based on UserControl). These controls render just fine at runtime, but they don't render in the designer.
I gather that this happens because the designer attempts to create an instance of the xaml root element, in this case my base class, but it can't create an instance because it is abstract.
For the record, I know that there are "patterns & practices" type issues with having this type of control hierarchy in WPF, but refactoring the entire project is not an option currently.
My question is this: I know that there are design time attributes for setting the DataContext, DesignWidth, etc. What I'm wondering is, can you give a "design time" instance or type to be provided as a replacement when the control is loaded in the designer?
in design time Visual Studio will try to create new Instant of YourUserControl
with parameterless constructor.
if you can't create usercontrol instant like this
var myView = new MyUserControl(); //no params
the designer will fail to render.
if YourUserControl required any parameter. the most popular trick is to create dedicate constructor like this
public MyUserControl() :
this(new MockViewModel(), new MockDataContext){ } // mock Designtime constructor
puclic MyUserControl(IViewModel vm, IDataContext context) //runtime constructor
{
}
in MVVM pattern some UserControl.DataContext is user-defined Type that required some params
XAML
<UserControl.DataContext>
<local:MyViewModel />
</UserControl.DataContext>
You must define parameterless constructor for design-time environment.
public MyViewModel() : this(new MockEventAggregator()) //for designtime
{ }
[ImportingConstructor]
public MyViewModel(IEventAggregator eventAggregator) //for runtime
{
this._eventAggregator = eventAggregator;
//...
}
I created a WPF Window
than i modified its class definition to:
public partial class myWindow : mySubclassedWindow
compiler throws:
"Partial declarations of 'myWindow' must not specify different base classes"
myWindow.Xaml:
x:Class="WpfGridtest.myWindow"
so somewhere, there is another partial class, that inherits from "Window" but i cannot find it. How can i override my case to use subclassed window?
thanks Jon, that was the problem.
also found this helpful article:
http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx
That would be in the declaration of myWindow itself - the designer will be generating the other half of the partial type based on the XAML, based on your element type.
You can use an element of <mySubclassedWindow> instead, so long as you give it the appropriate namespace and assembly references.
EDIT: Okay, so here's a short example, in a project called WpfApplication. My Window subclass:
using System.Windows;
namespace WpfApplication
{
public class EnhancedWindow : Window
{
}
}
My XAML:
<y:EnhancedWindow x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:WpfApplication"
Title="MainWindow" Height="350" Width="525">
</y:EnhancedWindow>
My partial type:
namespace WpfApplication
{
public partial class MainWindow : EnhancedWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}
It all builds with no problem. I think that's what you wanted to do, right?
I am new to WPF and have created a WPF User Control Library
I added a Base class that looks like this
public class TControl : UserControl
{
}
and want all of my controls to inherit from it.
I have a Control called Notification which looks like
public partial class Notification : TControl
{
public Notification()
{
InitializeComponent();
}
Works fine except when ever i recompile the hidden partial class where InitializeComponent() is defined gets regenerated and inherits from System.Windows.Controls.UserControl
this gives me an
Partial declarations of 'Twac.RealBoss.UserControls.Notification' must not specify different base classes
error,
is there anyway to force the generated class to inherit from my base class?
Your XAML file probably has:
<UserControl x:Class="YourNamespace.Notification" .... >
Try changing this to:
<Whatever:TControl x:Class="YourNamespace.Notification" xmlns:Whatever="clr-namespace:YourNamespace" />
The error you are getting is because the use of UserControl in the XAML tells the compiler to produce a partial class inheriting from UserControl, instead of inheriting from your class.
You can completely remove the ": TControl":
public partial class Notification : TControl
{
}
and write:
public partial class Notification
{
}
instead, since the base class is defined in the XAML part, as Paul wrote.