Form designer breaks on generic abstract UserControl - c#

I have a generic abstract UserControl class, SensorControl, which I want all my sensor control panels to inherit from.
The problem
When attempting to design the EthernetSensorControl (one of my inherited UserControl forms, from within Visual Studio, the following error is displayed in the form designer:
The designer could not be shown for this file because none of the classes within it can be designed. The designer inspected the following classes in the file: DeviceSensorControl --- The base class 'Engine.Sensors.SensorControl' could not be loaded. Ensure the assembly has been referenced and that all projects have been built.
SensorControl class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Engine.Sensors
{
public abstract class SensorControl<SensorType>
: UserControl where SensorType : class
{
protected SensorType _sensor;
public SensorControl(SensorType sensor)
{
_sensor = sensor;
}
}
}
Example inherited class, EthernetSensorControl:
namespace Engine.Sensors
{
public partial class EthernetSensorControl
: SensorControl<EthernetSensor>
{
public EthernetSensorControl(EthernetSensor sensor)
: base(sensor)
{
}
}
}
And the call stack:
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.EnsureDocument(IDesignerSerializationManager manager)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at System.ComponentModel.Design.Serialization.BasicDesignerLoader.BeginLoad(IDesignerLoaderHost host)
Everything compiles and I can see the panel displayed, but I can't design it. I think the problem may be related to the partial classes. Any ideas?

You cannot design a control or form that inherits an abstract class.
(The designer needs to instantiate the base class to serve as the design surface)
The base class also needs to have a parameterless constructor for the designer to call.
This constructor can be private.

Related

c#: Problems with the namespaces

I am having a problem with Visual Studio 2015 and Framework 4.6.1.
I have a business layer with this namespace: BusinessLayer.LocalStorage. In this class (named LocalStorage) I have this function:
...
public static void XXX()
{
}
...
In the main project with the same Framework 4.6.1, I have in one Winform
using BusinessLayer.LocalStorage;
In the Load I wrote the function but the reference is not recognized:
I have to add LocalStorage before:
LocalStorage.LocalStorage.XXX();
This way the call is working
why is not working using LocalStorage.XXX()? I declared my namespace in the using clausules.. Then should be working.
I have the class in a directory inside BusinessLayer project for this reason namespace should be BusinessLayer.LocalStorage
Code is:
namespace BusinessLayer.LocalStorage
{
public class LocalStorage
{
...
public static void XXX()
{
}
...
}
}
This is because LocalStorage is ambiguous, it could either be namespace LocalStorage or the class LocalStorage. You can solve this in 3 ways:
Remove the namespace LocalStorage entirely and move everything in it inside the BusinessLayer namespace
Rename the class LocalStorage to something else
Add using LocalStorage = BusinessLayer.LocalStorage.LocalStorage to the top of your file where you need to use the class LocalStorage
Edit: Option 4. If you desperately want to keep the directory structure as it is right now (with a LocalStorage directory), you can alternatively tell Visual Studio that the directory LocalStorage is not a namespace provider. You can do this by editing the properties of the folder in the Solution Explorer
Visual studio automatically generates Namespaces based on the current location of a class within a solution. When you create a new class it first takes the name of the project. Then it takes the current folder the class is located in. it will continue appending the folder name to the namespace until it reaches the class name itself.
So for example, if you have a project called ExampleProject, with a folder called Models, with a class inside called BaseModel.cs, the resulting namespace would be ExampleProject.Models
Make sure the namespace containing XXX is not LocalStorage.LocalStorage and is called BusinessLayer.LocalStorage. You can change this namespace to whatever you want and rebuild your project.
Although the namespace structure and object names are not recommended to be the same, which will lead to errors in many cases, I see that you want to use it this way from the comments you made.
I don't recommend you to name a class like its namespace, see this article
I would recommend would be <XYZ>LocalStorage.cs
I don't know your layer structure, but you can call it LocalStorage.XXX () with a structure like the one below.
BusinessLayer structure:
LocalStorage Class:
namespace BusinessLayer.LocalStorage
{
public class LocalStorage
{
public static void XXX()
{
}
}
}
And finally, after referencing BusinessLayer to winForm, you can call it in Load method as follows.
using System;
using BusinessLayer.LocalStorage;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
LocalStorage.XXX();
}
}
}
Or, if you don't want a folder in your BusinessLayer structure, you can use it using the same namespace (namespace BusinessLayer.LocalStorage) as below.

Is it necessary to inherit System.Windows.Application base class for WPF Application?

In VS2015, when we generated new WPF project, it contains App.xaml(.cs). I suppose that it will be an entry point of WPF application. Then App.xaml.cs becomes like:
...
using System.Windows;
namespace WpfApplication
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
Now, I remove inheritance of System.Windows.Application, still it seems to be working...
- public partial class App : Application
+ public partial class App
So let me ask: App class does not need to inherit System.Windows.Application? What is the difference?
thanks.
No it is not required. In your code you have the class defined as partial, this allows your code and autogenerated code by the compiler to be combined.
In your App.xaml you have
<Application x:Class="WpfApplication.App" ...
This tells the compiler you are creating a object of type Application with the name WpfApplication.App so the auto-generated code will include the inherited type class. Once your WpfApplication.App code is combined with the auto-generated WpfApplication.App the inheritance is already defined.

MvvmCross MvxWindowsPage<TViewModel> compilation error

I am writing a Xamarin.iOS, Xamarin.Android and UWP cross-platform application with the MvvmCross framework.
I am making a LoginPage which has a LoginViewModel. In the Xamarin.iOS, Xamarin.Android projects, the binding of the ViewModel and the View with below works just fine
public class LoginActivity : MvxAppCompatActivity<LoginViewModel>
public partial class LoginViewController : MvxViewController<LoginViewModel>
Trying to do the same as above on UWP project, I get some error.
In XAML:
<views:MvxWindowsPage
x:TypeArguments="viewModels:LoginViewModel" x:Class="MyApp.UWP.Views.LoginView"
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:views="using:MvvmCross.WindowsUWP.Views"
xmlns:viewModels="using:MyApp.PresentationCore.ViewModels"
mc:Ignorable="d">
And my C# code is
public sealed partial class LoginView : MvxWindowsPage<LoginViewModel>
But I get compilation errors. How can I resolve them?
`Unknown member 'TypeArguments' on element 'MvxWindowsPage'
The name "LoginViewModel" does not exist in the namespace "using:MyApp.PresentationCore.ViewModels".
GenericArguments[0], 'System.Object', on 'MvvmCross.WindowsUWP.Views.MvxWindowsPage`1[TViewModel]' violates the
constraint of type 'TViewModel'.
I think the errors are a little ambiguous because at the first error there is no templated version, but the third error is about a template constraint violation.
I know there is an option binding the ViewModel and the View with naming convention or attributes, but I would like to use this strongly typed solution.
Unfortunately I believe UWP does not support TypeArguments and subsequently generic types parameters for a base pages. You can check out the Prism GitHub thread where they discuss it. So you will have to go with one of the other registration options.
Mvvmcross offers various alternative approaches for registering your View to a ViewModel. During initialisation of Mvvmcross it will attempt to register your ViewModel to your View using MvxViewModelViewTypeFinder in the following order:
Attribute based registration:
You can add MvxViewFor attribute to your page class.
[MvxViewFor(typeof(FirstViewModel))]
public sealed partial class FirstView : MvxWindowsPage
{
public FirstView()
{
this.InitializeComponent();
}
}
Concrete type based registration:
You can register your View to your ViewModel by specifying the concrete type of the ViewModel.
public sealed partial class FirstView : MvxWindowsPage
{
public new FirstViewModel ViewModel => base.ViewModel as FirstViewModel;
public FirstView()
{
this.InitializeComponent();
}
}
Or in the case of Android and iOS where generic base class can be used:
// Android
public class FirstActivity : MvxAppCompatActivity<FirstViewModel>
// iOS
public class FirstViewController : MvxViewController<FirstViewModel>
Convention based registration:
You can have your view and ViewModel follow the same naming convention and Mvvmcross will map them for you (xxxView and xxxViewModel)
View
public sealed partial class FirstView : MvxWindowsPage
{
public FirstView()
{
this.InitializeComponent();
}
}
ViewModel
public class FirstViewModel : MvxViewModel

creating a class like App.xaml.cs in Class Library Project

So recently; I refactored Views to their own WPF Application project and I moved my ViewModel classes into their own Class Library project. This worked well for keeping my code in order. Then I realised that I didn't have the comfort of the App.xaml.cs class.
This class (for me) meant that I could declare all sorts of objects and access them application wide.
i.e: In the App.xaml.cs
public partial class App : Application
{
public myDatabaseEntities context { get; set; }
// App.xaml.cs Constructor
public App()
{
context = new myDatabaseEntities();
}
}
In some random View Model:
myDatabaseEntities context = ((App)Application.Current).context;
The above allows me to recylce the instance, and comes in particularly handy with Unity's (IoC container) version of lifetime manager.
Thing is, I'm not sure on how to achieve this behaviour within a class Library project. I'm not sure how to create a class that instantiates at runtime. And I have no clue how to pass that App class instance around to relevant classes. Any ideas on how to do this? Any help would be much appreciated.
Personally, I would keep all the "functionally" related Views and ViewModels together (next to each other). You may want to create class libraries (or modules) based for different functional parts of the application. Also, please refer to this MSDN page on building composite application using WPF and Prism.
Coming to your question, have an interface called IApplication defined something like this:
public interface IApplication
{
MyDatabaseEntities Context { get; }
}
and implement that interface on App class:
public partial class App : Application, IApplication
{
public MyDatabaseEntities Context { get; set; }
// App.xaml.cs Constructor
public App()
{
Context = new MyDatabaseEntities();
}
}
In your App.xaml.cs, as part of bootstrapping your application register this App instance with the container by calling RegisterInstance extension method on Unity container:
Container.RegisterInstance(typeof (IApplication), this, new ContainerControlledLifetimeManager());
Now, if your ViewModels take a dependency on IApplication, then they will have access to your App object and to the Context property via this interface. In future you could expose additional properties like: Dispatcher, Resources, etc from your App object through this interface.
Turns out all I needed was a regular class without the xaml front end. Then inherit the Application class. And lastly set it as the base class for app.xaml.cs. The answer is already here

Adding new installer class in windows application getting compiler error

I have created a widows application with setup project. I compiled and build.Everything looks fine.
For changing the configuration file during installation am trying to add a new Installer file. when i add it by default i get the below code
Collapse | Copy Code
[RunInstaller(true)]
public partial class Installer : Installer
{
public Installer()
{
InitializeComponent();
}
}
When i compile this Am gettin
Circular base class dependency involving 'windows_setup.Installer' and 'windows_setup.Installer'
windows setup is the name space i used for the application. Then i found that i need to create the new classs which inbherits Installer.So i changed my class name to
public partial class MyInstaller : Installer
Now am Getting
Inconsistent accessibility: base class 'windows_setup.Installer' is less accessible than class 'windows_setup.MyInstaller'
Suggest your ideas.
Thanks
Well, you can't have a public class inheriting from an internal class for example. Try to set everything as internal if not required outside, or public otherwise.
Either change class Installer and MyInstaller to public.
Write Something like this:
System.Configuration.Install.Installer and class definition should be public partial
[RunInstaller(true)]
public partial class MyInstaller : System.Configuration.Install.Installer
{
public MyInstaller()
{
InitializeComponent();
}
}

Categories