What is the best way to access components (e.g. imagelist, timer) from a form instance? I am working on multi form windows forms application on .NET Compact Framework version 3.5 SP1 with C#. I have a Controller class associated with each form for MVC implementation. Here is my sample Controller class.
public class Controller
{
public void Init(Form f)
{
//f.Controls will allow access to all controls
//How shall I access imagelist, timer on form f.
}
}
My question is how can I access non visual components without taking a performance hit of reflection? Any code snippets are welcome. If reflection is only way, then can you provide me optimal way for components access please?
Thanks,
You should be passing a strongly typed form or interface implementation which either exposes the controls directly (not the preferred choice) or abstracts the operations on the view into methods/properties which can be called from the controller (the preferred choice).
No, reflection is not the way. In terms of simply accomplishing what you're going for, you can expose a read-only property that returns the control. For example, say you have an ImageList named imageList1 on your form:
public ImageList ImageList
{
get { return imageList1; }
}
You can then access the ImageList property to get a reference to imageList1.
HOWEVER
This is smelly code. What you should expose is properties and functions that relate to what you need to DO with the ImageList. Your external code should not care about the particular implementation on your form (in other words, it should know you need to do something with images and provide functions to accomplish those actions; it shouldn't need to know that it's an ImageList control).
Related
My project is build on MVVM. Currently I have a list where i can select an object and add them to another list. What I want to make is a new window where this list is shown (the list with objects that are added) and edit that list in the new window (delte an item from that list).
How should I pass the data (selected object) to another window and be able to update them there?
I currently have it working in one view. In some related questions they advice MVVM light so I tried looking for that, from what I red mvvm light is mostly used to replace the notify property change. Should I use mvvm light or are there some specific patterns I could use?
Both windows will be open at the same time.
If you want to share your ViewModel between windows, you can use a ViewModelLocator. It is not specific to MvvmLight, it just creates one for you with its project template. You can implement it yourself, it is basically a container for your ViewModels. You can look here for the implementation details.
I've got to say that I'm not sure that these are the best approaches and if they are common, it's just what me and my colleagues were using in a WinRT application, so I'll be really glad if someone comes up with something better (both of these are not that clean).
I can think of two ways to pass data (without persisting it)
Pass parameters on page navigation
Have common shared class (Static or singleton class with some common data accessible from all ViewModels)
For passing on navigation:
I have this method in my Navigation service class:
public virtual void NavigateTo(Type sourcePageType, object parameter)
{
((Frame)Window.Current.Content).Navigate(sourcePageType, parameter);
}
and I use it like this in navigation commands:
Navigation.NavigateTo(typeof(PageType), someParameters);
Then you could get the values in the code behind of the navigated page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var receivedParameter = e.Parameter as TheTypeOfThePassedParameter;
}
And from there to pass them to the ViewModel, maybe there is an option to pass this without code in the code behind but I've not tried this.
Having shared class:
This is pretty much straightforward just have static class or a singleton with the desired fields.
I am pretty new to programming in c#. I have a listview (ListViewProjects) box in ProjectListForm but I want to be able to access the items in the listview box in AddProjectForm. How can I access them? I was going to try to do something like this
ProjectListForm.ListViewProjects.Items.Clear
but when I type in ProjectListForm., ListViewProjects isn't an option.
You can either set the list view's design time options to generate a public member (in control's properties, under Design set Modifiers to Public), or possibly better you could add a public property to ProjectListForm to expose either the list view or just the Items collection, eg:
public class ProjectListForm : Form
{
...
public ListView.ListViewItemCollection ProjectsListViewItems
{
get { return ListViewProjects.Items; }
}
}
The best way IMO is to write public methods in ProjectListForm that do what you're trying to achieve in AddProjectForm, such as ProjectListForm.ClearProjects(). That way you're not forcing AddProjectForm to depend on the implementation of ProjectListForm, say if you later want to change to a TreeView.
You cannot achieve this way in C#. you need to create the instance of the object.
To do this you have to create the method in ProjectListForm and in that methos you have to call this.ListViewProjects.Items.Clear.
Now from the AddProjectForm you have to call this method of the running instance of ProjectListForm.
If you want to know more about how to make the call, then please give the flow about how do you show the AddProjectForm from the ProjectListForm.
How do I populate a Form from within a method in a class library? So in the example below Method1() is what's it about.
Project "UI", Windows Forms Application
reference to MyLib
public class Form1 : Form
{
...
call some methods from MyLib.MyClass
...
}
Project "MyLib", Class Library
public class MyClass
{
...
public void Method1()
{
loop through an array and ask user to validate some data on the form during each iteration
}
}
UPDATE:
To be more specific, the MyLib library contains a class that will load a .csv file into an array (which for each row will be added to a List<string[]>) and than will loop through the List<string[]> looking for "possible" duplicates. Whenever one is found the user needs to be presented (on a Form) with both records to ultimately decide if they are the same.
How do I populate a Form from within a method in a class library?
The real question is why would you want to? The library should not be responsible for something like this. This is logic specific to your workflow and UI, not something a library is typically used for. The library should provide useful data structures, but things that are specific to your application (like gathering input and deciding what to do with it) should be handled by your code.
Anyway... I feel a bit dirty saying this... you could always just pass a reference to your form type as an argument to the method (an approach that will, among other things, tightly couple the two assemblies, making one unusable without the other)...
shudder
You may use Cross/Circular-referencing but this is not advisable due to several reasons.
You may also declare a Form-type object(better if static) within the class library and pass that form as reference and you may call the child controls within that referenced variable through the member "Controls" if I'm not mistaken.
Even though Ed put that final comment in, DO NOT DO IT! Of course it's possible, but it makes no sense. Resist the temptation!
The library should implement some general functionality, i.e. provide data structures, logic methods or maybe P/Invoke methods. But in your form class is where the logical for your UI goes. Just make a method in Form1 to handle the validation. It would be a lot easier and a lot clearer.
It's a vast question.
The easiest way would be to add a reference to System.Windows.Forms in your class lib. Then, pass the window as an argument to your business class.
But although easy this solution is, it's not a clean way. In a clean layered architecture, you can't use objects of upper layers in lowers layers. It can be both a challenge to compile and a maintenance black hole. Moreover, unit testing such cases are complex.
Considering this, another solution, a bit more complex, would be to use inversion of control, using a framework like Unity, Mef or any other, or even doing it manually.
The main idea would be to create in your class library an interface that defines user interactions like this :
public interface IInputValidator {
bool IsValid(MyClass itemToValidate);
}
Then, in you windows form application, implement this interface :
public class Form1 : Form, IInputValidator {
public void CallBusinessClass() {
var myObj = new BusinessClass(this); // the key of the concept is here
myObj.Iterate();
}
public bool IsValid(MyClass itemToValidate) {
return MessageBox.Show("Is valid ?", MessageBoxButtons.YesNo) == MessageBoxButtons.Yes);
}
}
Then, in you business class :
public class BusinessClass {
private IInputValidator m_validator;
public BusinessClass(IInputValidator validator) {
this.m_validator = validator;
}
public void Iterate()
{
foreach(var item in ItemsToIterate)
{
var isValid = m_validator.IsValid(item); // call the upper layer from a lower layer
}
}
}
hope that helps
I'm fairly new to .Net... I have several queries which will execute when the application loads. I want these queries to store the data in an object (a dataset?) which is accessible throughout the application. Should I be using a singleton class? How can a User Control within my application reference public variables in the main application code?
I guess I haven't found a good resource on how / where to store application variables and how to reference them when I need to populate a ListBox, DataGridView, etc.
As a background I'm most familiar with developing using Flex Builder 3, sorry for the vague question... I'm having a problem locating a good reference on the topic (not just populating a Control, but storing the data at an application level and referencing it from anywhere within the app).
Edit: This is for programming a windows forms application using C#
Sounds like you're using ASP.NET, in which case Application State (MSDN) will allow you to store and retrieve application-wide data that can be accessed from anywhere in the application.
More here:
How to: Save Values in Application State
How to: Read Values from Application State
If you're writing a desktop app, you should create a static class that contains your application wide data, e.g:
public static class ApplicationSettings
{
public static string InstallDirectory { get { ... } set { ... } };
public static DataSet SomeDataSet { get { ... } set { ... } };
static ApplicationSettings()
{
// ... initialize or load settings here
}
}
A singleton isn't necessary here, but if you do require lazy initialization and thread satefy you might want to take that route.
You could store the information in a App.config file and use the AppSettingsReader class to access the data.
EDIT: Seeing that you don't want to query the information multiple times, you could use a Singleton to access and cache the data.
Presumably your objects will be required as long as the application's main form is open. If so, simply store them as properties of the form.
Singletons are bad, m'kay? ;)
Or, more to the point, global data (especially mutable global data) is generally not a good thing. It makes classes difficult to test and debug. Small scope is good scope.
One option is to look at an IoC Container library (aka a DI framework).
IoC = Inversion of Control
DI = Dependency Injection (or Inversion)
Basically you can set up constructors on your classes that need access to the global data and add a parameter of your "singleton" type - except it's not a singleton, just a Plain Old Object (or interface). Then you tell the Container that your "global data" class has a long lifespan, and use the Container to create your other objects. You won't use the "new" keyword much anymore. The benefit is that the Container will automagically wire everything up for you, creating one and only one instance of the global class and injecting it in to all of the other constructed objects.
Here's an (incomplete) list of the libraries/frameworks for .NET:
IoC Container Benchmark
Ninject's another one. I use Unity, but that doesn't mean it's the best for you.
Here's another list:
http://elegantcode.com/2009/01/07/ioc-libraries-compared/
I have a set of functions I want to be available to my web pages and user controls in my c# .net 3.5 web project. My standard approach for pages is to create a "base page" that extends the System.Web.UI.Page class and then have my pages inherit from this, rather than directly from the Page class.
I now want to expose some of these functions to my web controls (ascx) and web services. I can think of a number of ways to do this, but they seem a little clumsy and I think I'm missing a trick.
Is there an easy way to provide some common functions to both my pages, web services and controls using inheritance, or do I need to wrap these functions in a class that all of them can access?
An example to clarify:
I have a singleton that handles most functionality for my web application.
At the start of each request I want to check that the class exists in the web cache and initialise it if not.
Initially this was handled in a page base that the pages all used. Now I need to be able to access my singleton safely from services and controls, with the same checks. I have therefore extracted the checking and initialisation logic into another class, that then each of my base page, control and web service, all instantiate. Even with this model I have the same code repeated in 3 places (each of my base classes for controls, ws and pages), albeit not much code, this seems wrong too!
It works, but it seems clumsy...I look forward to you guys humbling me with your wisdom!
Sounds to mee like a case of aspect-oriented programming. .NET is ill equipped for this. I'm afraid that your solution is one of the best.
Alternatively perhaps you can move all or some of those functions to a static class/singleton and then use that class from your aspx/ascx/asmx? Not much in the way of inheritance, but at least less code duplication.
My solution to this is to put all the methods and functions I want to share in my base master page class. I then put an equivalent for each method and function in the user control base class as follows:
//Property in masterpage base
public string QsSearchTerm
{
get
{
if (!String.IsNullOrEmpty(Request.QueryString["q"]))
{
return Helpers.SanitiseString(Server.UrlDecode(Request.QueryString["q"]));
}
return String.Empty;
}
}
//Property in usercontrol base
public string QsSearchTerm
{
get
{
if (Page.Master is BaseMasterPage)
{
return ((BaseMasterPage)Page.Master).QsSearchTerm;
}
return string.Empty;
}
}
What this doesn't help with, is your code repetition with web service base classes. I would think that refactoring the above into a class with a constructor that accepts an HttpContext instance would be the way forward. You can then expose a singleton instance of this class in your base web service, master page, user control, page etc.
Hope this helps, but I too would be interested in hearing if there's a better way.
In your Singleton you could provide a Strategy interface to allow variations of the code depending on the configured environment. This would allow you to switch between web/windows/wcf...and so on.
I think using a BasePage is the right approach.
I have multiple base pages and custom user controls that load differently depending on which basepage is used by the current page.
In your custom user control you can use something like:
if (this.Page is BasePageName)
{
BasePageName bp = (BasePageName)this.Page;
bp.BasePageFunction();
}
No you can get ride of the repetitive code in the custom user control and just call it from the base page.
You can also have a hierarchy of inherited base pages depending on page functionality and needs. ie.) BasePageName2 : BasePageName