I am working a project in gui builder..As my project is growing bigger and bigger, i find it hard to search a particular forms and methods all in a statemachine class. so i wanted to create a separate class for each form. but since the gui builder create the methods automatically in statemachine which extends statemachineBase class. how can i use separate class for separate gui forms so that they automatically create methods in the designated class. for instance when i click before show event of form named "NextPage", the gui builder automatically create beforeNextPage method in NextPage class instead of statemachine. I did the followings but lost in the process..
NextPage.class
public class NextPage extends StateMachine {
private ArrayList<Map<String, Object>> mData;
private ArrayList<Map<String, Object>> moreData;
public NextPage(String resFile) {
super(resFile);
}
#Override
public void beforeNextPage(Form f) {
//.........
}
}
Forms generated by GUI Builder cannot be separated from StateMachineBase into different Classes.
What I do personally is create a form in GUI to get the right Look and Feel and then create a replica of that form in code, then delete the one on GUI Builder once I'm satisfied with the code version. It makes my projects well organized and easy to debug.
BeforeShow() would be handle while the form class is loading and to do anything in PostShow(), just do this:
this.addShowListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
removeShowListener(this);
//Your postShow() codes here.
revalidate();
}
});
Forms created in code are light-weight and more customizable than GUI forms.
Related
Suppose I have a Windows WPF application (SampleApp) that is using IoC (Ninject). I have wired up everything in my composition root as follows.
[STAThread]
static void Main()
{
IKernel kernel = new StandardKernel();
var modules = new List<NinjectModule>
{
new ExternalDependencies(),
new DependencyResolver()
};
kernel.Load(modules);
var mainWindow = kernel.Get<IMainWindow>();
mainWindow.ShowDialog();
kernel.Release(mainWindow);
kernel.Dispose();
}
The Conents of ExternalDependencies can be ignored for this example, but here are the contents of DependencyResolver which is for internal dependencies.
class DependencyResolver : NinjectModule
{
public override void Load()
{
Bind<IMainWindow>().To<MainWindow>().InSingletonScope();
Bind<IProductWindow>().To<Product>().InSingletonScope();
}
}
As you can see, I have MainWindow and Product wired up. The ctor on MainWindow looks as follows.
public MainWindow(IDomain<TaskFields, TaskExtFields, TaskEmbeds> task)
{
_task = task;
InitializeComponent();
}
We're all good to this point. However, now I am at the point where I would like to have actions in the main window (button clicks, menu selections, etc) open various other forms. For example I have a Product window as follows and I want a button click to open the window and wire everything up appropriately.
public Product(IDomain<ProductFields, ProductExtFields, ProductEmbeds> productDomain)
{
_productDomain = productDomain;
InitializeComponent();
}
Looking to keep my IoC from leaking out of the Main method. In other words I don't want the code to look like...
var productWindow = GlobalIoC.Get<IProductWindow>();
which would violate the three R's principle, require me to make the IoC global and leak information that I hope is not needed out into the rest of the code.
Right now I am dealing with 2 or 3 windows for testing - however in a final application I can see this growing to a larger number, say perhaps hundreds of windows each with their own backing viewmodels (when I get through this I will be implementing viewmodels), domain, data models, repositories, etc.
I have all of this working for the main form but I cannot wrap my head around how to properly wire everything up so that it's available, and stays in the composition root.
To be clear, this is currently a learning project (IoC, MVVM, DI)
Suggestions?
I am very new to WPF and MVVM Pattern. I even have no experience on windows.
I have Created Simple login window
_ Login.xaml, LoginViewModel.cs
_ Dashboard.xaml, DashboardViewModel.cs
After Login Successfully - ( In Login time we will select Language also )
I am Displaying Username & Selected Language in Dashboard window
I wrote code like this:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
try
{
var login = new Login();
var loginVM = new LoginViewModel();
Dashboard main = null;
loginVM.LoginCompleted += (sender, args) =>
{
DashboardViewModel dvModel = new DashboardViewModel(loginVM);
main = new Dashboard();
main.DataContext = dvModel;
main.ShowDialog();
login.Hide();
};
login.DataContext = loginVM;
login.ShowDialog();
}
catch (Exception ex)
{
throw ex;
}
}
In Dashboard Window it is displaying username and Language successfully.
But my problem is those two (Username & Language) properties I want to use in dashboard codebehind for update the layout based on language & other xaml files or other viewmodels . How to do that one ?
Technically I want to use Loginviewmodel object in all viewmodels.
Based on Selected Language I want to update Layout.
Note: Is this login approach good ? Is there any alternative for Globalization in MVVM pattern ?
Using a ViewModel for login is perfectly valid. I would perhaps create a token in your loginVM to pass around the system, depending on your needs. That token should be passed into the constructors of your other viewmodels from your main view model (DashboardViewModel?). This can be resolved using any decent IoC container.
For globalization/localization, I would use resources (in satellite assemblies). We've experimented with various things, and found that we didn't like the WPF UUIDs added everywhere when using LocBaml. And storing translation is a database quickly became a performance hog (even when loading in bulk). This does require you to find your labels etc. to a resource manager, but in my opinion, it is worth it.
Take a look at this article, for a nice extension, that enables you to simply write:
<TextBlock Text="{Resx MyText}"/>
And it will be translated using resource files.
An alterative approach is to simply store the Username and Language is a static property. I know most people don't like globals, but something like this is in nature very global, and you will still be able to inject it in if you so desire. The downside of this approach is that your unit tests would have to setup this static variable first.
EDIT An example of the static approach:
public static class RuntimeInfo {
public static string UserName { get; set; }
public static CultureInfo UserCulture { get; set; }
}
In your loginVM, simply store the necessary values in a static class. This can be accessed anywhere needed. This is not as 'correct' as the previous approach, but it can be more pragmatic than having to pass the username into every single ViewModel in your application.
I still recommend injection through an IoC container though.
I want to use the exportWizard extension point for an eclipse plugin. I am having some difficulties figuring out how a simple filedialog wizard page should look like.
public class ExportWizardPage extends WizardPage {
private FileDialog fileDialog=null;
protected ExportWizardPage(String pageName) {
super(pageName);
}
#Override
public void createControl(Composite parent) {
fileDialog = new FileDialog(parent.getShell(), SWT.SAVE);
fileDialog.setFilterExtensions(new String[] { "*.bm" });
}
}
I am trying it currently like above and use a FileDialog for selecting the target file. Basically it works, the dialog is opened and I get the name of the file, but as soon the dialog closes I get an exception.
org.eclipse.core.runtime.AssertionFailedException: null argument:
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:85)
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:73)
at org.eclipse.jface.wizard.Wizard.createPageControls(Wizard.java:178)
I think I am using this Wizard/WizardPage mechanism wrongly, but I really could not found a simple example that showed me how something should look like.
Your wizard page does not contain any controls. You should create one composite and then add all your controls to it (and NOT parent directly). Calling setControl(..) is also absolutely required. It should look something like this:
#Override
public void createControl(Composite parent) {
Composite content = new Composite(parent, SWT.NONE);
// add all the controls to your wizard page here with 'content' as parent
FileDialog fileDialog = new FileDialog(parent.getShell(), SWT.SAVE);
fileDialog.setFilterExtensions(new String[] { "*.bm" });
setControl(content);
}
How do I handle situations in which I need pre-existing data before the app is started or right after the database is generated. For example, I have a list of countries in which I'd like to load into the database after code-first generates it. How do I do this?
App is structured as follows:
Repository > Service > WebMVC
The xml is in the WebMVC project.
You create custom initializer, which inherits from DropCreateDatabaseIfModelChanges or DropCreateDatabaseAlways interface. Like:
public class EntitiesContextInitializer : DropCreateDatabaseIfModelChanges<-YourDbContext->
And then you overwrite Seed method like:
protected override void Seed(YourDbContext context)
Whole example might look like:
public class EntitiesContextInitializer : DropCreateDatabaseIfModelChanges<EntitiesContext>
{
protected override void Seed(EntitiesContext context)
{
List<Role> roles = new List<Role>
{
new Role {Id=1, Title="Admin"},
new Role {Id=2, Title="ProjectManager"},
new Role {Id=3, Title="Developer"}
};
// add data into context and save to db
foreach (Role r in roles)
{
context.Roles.Add(r);
}
context.SaveChanges();
}
}
Edit: After setting this up, you have to set up Initializer too, as Ladislav Mrnka mentioned.
Database.SetInitializer(new EntitiesContextInitializer());
ie.: in Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Database.SetInitializer(new EntitiesContextInitializer());
}
Don't forget to add using System.Data.Entity;
.....
You must create custom database initializer derived for example from DropCreateDatabaseIfModelChanges and fill data in overriden Seed method. Then you must use Database.SetInitializer to set your new initializer when application starts. Here is example (from CTP5) used to create custom index in the database.
For an example see the new MVC / Entity Framework tutorial series at
http://www.asp.net/entity-framework/tutorials#Using%20MVC
Both #1 and #4 show initializer classes.
What are the requirements for a custom data source to be listed in the 'Data Source' drop-down list when adding a Dataset to a .rdlc report in Report Viewer 2010?
As can been seen from the screen grab, for some reason it is listing potential sources from a variety of referenced assemblies, but I can't see an obvious pattern as to why it is selecting these.
The 'GeneralDataSet' makes sense as that is a strongly-typed Dataset class, but I'm pretty sure most of the others are not, yet the design dialog still lists them.
I'm looking to roll my own custom data source and would prefer it to be selectable from this list.
I think it scans your project file looking for methods that return Lists<> and so on.
So something like:
public class Person
{
public string name { get; set; }
public int age { get; set; }
}
public class GetPeople
{
public List<Person> GetPeopleList()
{
return null;
}
public IEnumerable<Person> GetPeopleIEnumerable()
{
return null;
}
public IQueryable<Person> GetPeopleIQueryable()
{
return null;
}
}
All three show up, so take your pick. (Code is just thrashed out, ignore bad names/practices :))
But when you use a ReportViewer, you will need to manually set the datasets. Selecting it inside the report from what I have found just basically tells it what data to expect. So add an ObjectDataSource or just set it in the code behind.
I noticed the dataset does not appear if the source is exposed as a Property and not a method.
ie this fails to be a selectable data source.
public class FooData
{
public List<string> Data {get;set;}
}
but this will show up as a data source
public class FooData
{
public List<string> GetData();
}
I just had a problem with this also,
my class was returning Lists but would not show up in the datasources list.
I then added a parameterless constructor and it started to show up ( there was not one before ) I assmume this is so the reportviewer can create and instance of it.
eg:
public MyObject()
{
}
I've had a similar problem with custom lists which inherit from List.
You can work around it if your system will allow you to inherit without using interfaces. Ours doesn't.
The project containing this class WILL appear in the DataSource dropdown, and the class itself appears in the DataSet dropdown:
public class AccountList : List<AccountData>
{}
This class will NOT appear as a Dataset, which prevents its project from appearing as a DataSource (notice the "I" in front of AccountData):
public class AccountList : List<IAccountData>
{}
This is a pain because other aspects of our system require the lists to inherit from an interface not a concrete class. I don't know why it doesn't work.