Loading Application.Resources properly in WPF / XAML - c#

In my WPF Application, I specify an Application.Resource, as shown here:
<Application x:Class="MyApp" [...]>
<Application.Resources>
<local:MyData x:Key="MyData">
</Application.Resources>
</Application>
I have a class MyData, which currently does all of its initialization (including loading data from a file) in its constructor. I consider this bad form, as I'm coming from a C++ background, where constructors should be kept minimal.
I suspect I want the MyData class to listen for an event, something like "AfterResourcesLoaded", but I haven't been able to find any description of this in searching MSDN.
Am I right that doing too much work in the constructor is bad form in C#, as it is in C++? Or is it acceptable to do significant work in the constructor?
How do I register an event-handler in MyData in the XAML, so that I can do the necessary work when the event is triggered, after the object is constructed?
(or perhaps I'm on the wrong track entirely? Alternative ideas gratefully considered.)

Doing too much work in the constructor of a class is also bad idea in C# as well as in C++ (mainly because it is not obvious for the users of the class).
What you can do is to have the data load triggered when it is accessed for the first time (e.g. in a property getter of the MyData class) or by providing an explicit method (e.g. LoadData) that can be called in the Application.Startup event handler. Something like this:
public class MyApp : Application
{
public override OnStartup(EventArgs e)
{
base.OnStartup(e);
MyData data = FindResource("MyData");
data.LoadData();
}
}

Assuming MyData is basically a simple class that just holds data, I'd move the responsibility of loading MyData out of itself and into another class. The other class could hydrate MyData in your application or Window's Loaded event.

Related

Having my Viewmodel appear in namespace dropdown

I'm trying to expose the ViewModel as a static resource on the page so that it can be easily accessible by the binding.
TestViewModel.cs
namespace Test.WPFUI.Home
{
public class TestViewModel....
HelloWorldView.Xaml
xmlns:local="clr-namespace:Test.WPFUI.Home"
<UserControl.Resources>
<local:TestViewModel x:Key="mainPageViewModel" />
</UserControl.Resources>
TestViewModel Can't be found. May I ask for some tips or suggestions Please.
Getting help from http://www.telerik.com/help/silverlight/gridview-troubleshooting-blank-cells.html
public class LoanViewModel : ScreenViewModelBase<LoanViewModel>, IRecord, INotifyPropertyChanged
{
public LoanViewModel(IEventAggregator events) .............
It sounds like your initial problem was not having the full xmlns definition. You usually need both the namespace and assembly.
The easiest way to get it right, in my experience, is to let intellisense do it for you. Just start typing the namespace you want, and as long as its in a referenced project, there will be an autocomplete option.
Your second problem is due to not having a default constructor. You wrote this:
<local:TestViewModel x:Key="mainPageViewModel" />
Which will invoke the default constructor. However, you define a constructor here:
public LoanViewModel(IEventAggregator events) .............
Which removes the provided (paramaterless) default constructor. I'm going to take a wild guess and say that creating the correct IEventAggregator is not simple or desired from XAML, so I see two choices:
You didn't really need that parameter in the constructor. Simply add a default constructor to your view model and you are good to go!
You really need that parameter, so instantiating from XAML just isn't a good idea. Pass in your view model from somewhere else on the view's constructor.
If you feel like you can instantiate the correct object from XAML, use this post to invoke the paramaterized constructor: Calling a parameterized constructor from XAML
In my opinion, putting truly regular classes into XAML is not a good pattern to follow, so I wouldn't. By regular, I mean not related at all to the view.

Does every little event published to an Event Aggregator need to be an empty CompositePresentationEvent of its own?

I am trying to understanding the Event Aggregator pattern from an architecture and design view point. I have never used Prism in WPF before, but I'm studying how it works on MSDN.
It seems to me that for every event, the user has to create a new event object that extends the CompositePresentationEvent. It also appears that the new event object has no functionality other than those it inherited from (it usually has no code for itself).
So for example:
A AddNewStuffEvent would look like:
public class AddNewStuffEvent : CompositePresentationEvent<Object> {} //The end of the class
For a HealthChangeEvent:
public class HealthChangeEvent: CompositePresentationEvent<Object> {} //The end of the class
For a BookFlipEvent:
public class BookFlipEvent: CompositePresentationEvent<Object> {} //The end of the class
For a BookCloseEvent:
public class BookCloseEvent: CompositePresentationEvent<Object> {} //The end of the class
And this can go on forever for every little small event for BookOpenEvent, BookTearEvent, etc. So, in a particular namespace folder, there will be a whole ton of event classes, and the Event Aggregator is going to be loaded with all these event objects during runtime. That's, every little small event needs an empty class? Is this how it works? What could be a better way for this?
Yes, every event type needs its own class, which you have to define.
It also appears that the new event object has no functionality other than those it inherited from
The purpose is simply to provide strong typing for the event. This makes it easier to write code to subscribe to them. Ie, the subscribing code can be written like:
aggregator.GetEvent<AddNewStuffEvent>().Subscribe(Handler);
This is a preferable approach to alternatives, such as reliance on "magic strings" in the form of say aggregator.GetEvent("AddNewStuffEvent").Subscribe(Handler) (which could not be verified at compile time.

WP7 Access MainPage Elements

I'm trying to make a simple Windows Phone 7 Silverlight app. There's the MainPage.xaml with some UI elements, and a separate C# class MyClass.cs with some code.
My problem is: MyClass can't access anything contained in MainPage (i.e. it doesn't know the UI elements or C# methods exist).
If I try to inherit MainPage, the app compiles, but refuses to run:
public class MyClass : MainPage
{
// No good
}
If I try this solution, then I get an InvalidCastException error:
public class MyClass
{
// Also no good
MainPage m = (MainPage)Application.Current.RootVisual;
}
My question is: how can I access MainPage from a separate class?
In MainPage.xaml.cs, I can simply use myElement.Property etc. However, this isn't possible in MyClass, but I'm not sure why.
I guess there's a simple answer that I'm missing, but I'm really not sure what it is (... C# newbie trying to run before he can walk!?).
Thanks in advance for any advice you can offer.
The answer is that you shouldn't be doing this as this level of coupling is likley to cause issues in the future in terms of reuse and particularly testing.
You could look at having a separate global view model which has the information (properties) you need and is bound to the view model of the main view.
If you need your class to call methods on the view then you could look at a messaging system or similar.

C# - Marking base class of custom Form makes Design View display HTML

Alright so. I have an app with several dialogs that have a handful of events that they all respond the same way to, and all have a few methods they provide to the Presenter. These have all been pushed up into a:
public abstract class BaseFormClass : Form
and all the other forms are:
public class DerivedFormClass : BaseFormClass
I've got a model-view-presenter setup going, so the base class has a few protected EventHandler<EventArgs>, and for each one is a similarly named function which is assigned to be called for that event, and a setter exists that the presenter can assign it's own function to be used as the handler for the event. (In other words:)
protected void OnFormBeginClosing(object sender, FormClosingEventArgs e)
{
if (formClosing == null)
return;
formClosing(sender, e);
}
public EventHandler OnFormClose
{
set
{
formClosing = value;
}
}
protected EventHander<EventArgs> formClosing;
Then the presenter uses the OnFormClose setter to set it's own handler function to handle any necessary cleanups or whatever's necessary.
Now that the backstory is out of the way, the main question is, why when I make the simple change of marking the parent Form as abstract does my design view of my child Forms go from the normal design view to just spitting out a mess of HTML (well, not a mess, a single line of what appears to be the entire HTML of the form...)?
Can anyone suggest what I might be doing wrong?
I have never tried this before, but trying the same in Visual Studio 2010, I get the error The designer must create an instance of type 'WinFormsTestApp.FormA' but it cannot because the type is declared as abstract.
I suspect this means exactly what it says - in order to display your derived form, for some reason known only to itself, the designer needs to create an instance of the parent form, and obviously can't do that. Sorry, but you will probably have to redesign your hierarchy. The VS designers make a lot of assumptions about the inheritance patterns used for forms and controls, so if you stray from the standard patterns, these problems are quite common.

'UserControl' constructor with parameters in C#

Call me crazy, but I'm the type of guy that likes constructors with parameters (if needed), as opposed to a constructor with no parameters followed by setting properties. My thought process: if the properties are required to actually construct the object, they should go in the constructor. I get two advantages:
I know that when an object is constructed (without error/exception), my object is good.
It helps avoid forgetting to set a certain property.
This mindset is starting to hurt me in regards to form/usercontrol development. Imagine this UserControl:
public partial class MyUserControl : UserControl
{
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
At designtime, if I drop this UserControl on a form, I get an Exception:
Failed to create component 'MyUserControl' ...
System.MissingMethodException - No parameterless constructor defined for this object.
It seems like, to me, the only way around that was to add the default constructor (unless someone else knows a way).
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
The whole point of not including the parameterless constructor was to avoid using it. And I can't even use the DesignMode property to do something like:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
if (this.DesignMode)
{
InitializeComponent();
return;
}
throw new Exception("Use constructor with parameters");
}
}
This doesn't work either:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
Fine, moving along ...
I have my parameterless constructor, I can drop it on the form, and the form's InitializeComponent will look like this:
private void InitializeComponent()
{
this.myControl1 = new MyControl();
// blah, blah
}
And trust me, because I did it (yes, ignoring the comments Visual Studio generated), I tried messing around and I passed parameters to InitializeComponent so that I could pass them to the constructor of MyControl.
Which leads me to this:
public MyForm()
{
InitializeComponent(); // Constructed once with no parameters
// Constructed a second time, what I really want
this.myControl1 = new MyControl(anInt, aString);
}
For me to use a UserControl with parameters to the constructor, I have to add a second constructor that I don't need? And instantiate the control twice?
I feel like I must be doing something wrong. Thoughts? Opinions? Assurance (hopefully)?
Design decisions made regarding the way Windows Forms works more or less preclude parameterized .ctors for windows forms components. You can use them, but when you do you're stepping outside the generally approved mechanisms. Rather, Windows Forms prefers initialization of values via properties. This is a valid design technique, if not widely used.
This has some benefits, though.
Ease of use for clients. Client code doesn't need to track down a bunch of data, it can immediately create something and just see it with sensible (if uninteresting) results.
Ease of use for the designer. Designer code is clearer and easier to parse in general.
Discourages unusual data dependencies within a single component. (Though even microsoft blew this one with the SplitContainer)
There's a lot of support in forms for working properly with the designer in this technique also. Things like DefaultValueAttribute, DesignerSerializationVisibilityAttribute, and BrowsableAttribute give you the opportunity to provide a rich client experience with minimal effort.
(This isn't the only compromise that was made for client experience in windows forms. Abstract base class components can get hairy too.)
I'd suggest sticking with a parameterless constructor and working within the windows forms design principles. If there are real preconditions that your UserControl must enforce, encapsulate them in another class and then assign an instance of that class to your control via a property. This will give a bit better separation of concern as well.
There are two competing paradigms for designing classes:
Use parameterless constructors and set a bunch of properties afterwards
Use parameterized constructors to set properties in the constructor
The Visual Studio Windows Forms Designer forces you to provide a parameterless constuctor on controls in order to work properly. Actually, it only requires a parameterless constructor in order to instantiate controls, but not to design them (the designer will actually parse the InitializeComponent method while designing a control). This means that you can use the designer to design a form or user control without a parameterless constructor, but you cannot design another control to use that control because the designer will fail to instantiate it.
If you don't intend to programmatically instantiate your controls (i.e. build your UI "by hand"), then don't worry about creating parameterized constructors, since they won't be used. Even if you are going to programmatically instantiate your controls, you may want to provide a parameterless constructor so they can still be used in the designer if need be.
Regardless of which paradigm you use, it is also generally a good idea to put lengthy initialization code in the OnLoad() method, especially since the DesignMode property will work at load time, but not work in the constructor.
I would recommend
public partial class MyUserControl : UserControl
{
private int _parm1;
private string _parm2;
private MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2) : this()
{
_parm1 = parm1;
_parm2 = parm2;
}
}
As this way the base constructor is always called first and any references to components are valid.
You could then overload the public ctor if need be, ensuring the control is always instantiated with the correct values.
Either way, you ensure that the parameterless ctor is never called.
I haven't tested this so if it falls over I apologise!
This is unfortunately a design issue that will occur frequently, not just in the control space.
There are often situations where you need to have a parameterless constructor, even though a parameterless constructor is not ideal. For example, many value types, IMO, would be better off without parameterless constructors, but it's impossible to create one that works that way.
In these situations, you have to just design the control/component in the best manner possible. Using reasonable (and preferably the most common) default parameters can help dramatically, since you can at least (hopefully) initialize the component with a good value.
Also, try to design the component in a way that you can change these properties after the component is generated. With Windows Forms components, this is typically fine, since you can pretty much do anything until load time safely.
Again, I agree - this isn't ideal, but it's just something we have to live with and work around.
Well, in short, the designer is the kind of guy that likes parameter-less constructors. So, to the best of my knowledge, if you really want to use parameter based constructors you are probably stuck with working around it one way or the other.
Just do this:
public partial class MyUserControl : UserControl
{
public MyUserControl() : this(-1, string.Empty)
{
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
if (parm1 == -1) { ... }
InitializeComponent();
}
}
Then the 'real' constructor can act accordingly.
Provide a parameterless constructor for the designer and make it private - if you really must do it this way... :-)
EDIT: Well of course this won't work for UserControls. I obviously wasn't thinking clearly. The designer need to execute the code in InitializeComponent() and it's can't work if the constructor is private. Sorry about that. It does work for forms, however.
It's quite a while since the question was asked, but maybe my approach is helpful to somebody.
I personally also prefer to use parameterized Constructors to avoid forgetting to set a certain property.
So instead of using the actual Constructor I simply define a public void PostConstructor where all things are put you would normally put in the Constructor. So the Actual Constructor of the UserControl always contains only InitializeComponent().
This way you don't have to adjust your favourite programming paradigm to VisualStudios needs to run the Designer properly. For this programming schema to work it has to be followed from the very bottom.
In practice this PostConstructionalizm would look somewhat like this:
Let's start with a Control at the bottom of your UserControl call hierarchy.
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
//setting parameters/fillingdata into form
}
}
So a UserControl containing the ChildControl would look something like that:
public partial class FatherControl : UserControl
{
public FatherControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
ChildControl.PostConstructor(YourParameters[])
//setting parameters/fillingdata into form
}
}
And finally a Form calling one of the User Control simply puts the PostConstructor after InitializeComponent.
public partial class UI : Form
{
public UI(yourParameters[])
{
InitializeComponent();
FatherControl.PostConstructor(yourParameters[]);
}
}
I have a way to work around it.
Create a control A on the form with the parameterless constructor.
Create a control B with parameterized constructor in the form contstructor.
Copy position and size from A to B.
Make A invisible.
Add B to A's parent.
Hope this will help. I just encountered the same question and tried and tested this method.
Code for demonstrate:
public Form1()
{
InitializeComponent();
var holder = PositionHolderAlgorithmComboBox;
holder.Visible = false;
fixedKAlgorithmComboBox = new MiCluster.UI.Controls.AlgorithmComboBox(c => c.CanFixK);
fixedKAlgorithmComboBox.Name = "fixedKAlgorithmComboBox";
fixedKAlgorithmComboBox.Location = holder.Location;
fixedKAlgorithmComboBox.Size = new System.Drawing.Size(holder.Width, holder.Height);
holder.Parent.Controls.Add(fixedKAlgorithmComboBox);
}
holder is Control A, fixedKAlgorithmComboBox is Control B.
An even better and complete solution would be to use reflect to copy the properties one by one from A to B. For the time being, I am busy and I am not doing this. Maybe in the future I will come back with the code. But it is not that hard and I believe you can do it yourself.
I had a similar problem trying to pass an object created in the main Windows Form to a custom UserControl form. What worked for me was adding a property with a default value to the UserControl.Designer.cs and updating it after the InitializeComponent() call in the main form. Having a default value prevents WinForms designer from throwing an "Object reference not set to an instance of an object" error.
Example:
// MainForm.cs
public partial class MainForm : Form
public MainForm()
{
/* code for parsing configuration parameters which producs in <myObj> myConfig */
InitializeComponent();
myUserControl1.config = myConfig; // set the config property to myConfig object
}
//myUserControl.Designer.cs
partial class myUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
// define the public property to hold the config and give it a default value
private myObj _config = new myObj(param1, param2, ...);
public myObj config
{
get
{
return _config ;
}
set
{
_config = value;
}
}
#region Component Designer generated code
...
}
Hope this helps!

Categories